动态规划——稀疏表求解RMQ问题
RMQ (Range Minimum/Maximum Query)问题,即区间最值查询问题,是求解序列中的某一段的最值的问题。如果只需要询问一次,那遍历枚举(复杂度O(n))就是最方便且高效的方法,但如果询问次数很多(m次),O(nm)的复杂度可能就不够看了。比较容易想到的优化方法是运用预处理的思想,可以在O(n^2)的时间内预处理出所有区间的最大值,随后每一次查询都只需要O(1)的时间。这种方法在n较小但m非常大的情况下很实用,但如果n也很大的话,无论是空间还是时间都接受不了这个复杂度。
这种情况下,我们可以借助稀疏表(sparse table)和动态规划的思想,避免笨重的逐个预处理的方法:
设dp[i][j]代表从第i个元素开始,长度为2^j的区间中的最值。那么dp[i][0]就等于原序列中的第i个元素,dp[i][j]则可以由两段长度为2^(j-1)的区间合并而成。这样,就可以在o(nlogn)的时间内完成预处理。在查询时,任一区间都可以被已经预处理出来的两个区间恰好覆盖,找出这两个区间即可完成查询。预处理的时间和空间复杂度都为O(nlogn),查询为O(1)。
下面以最大值为例,附上实现代码和需要注意的细节。
1、预处理
int n;
int a[maxn], dp[maxn][maxj];//a为原序列,元素编号为1至n
void init()//预处理
{
for(int i = ;i <= n;i++)//初始化
{
for(int j = ;j < maxj;j++)
{
dp[i][j] = -INF;//这里可根据需要赋成其他值或是省略,此处为无穷小
}
dp[i][] = a[i];//dp的初始值
}
//因为状态转移是把两段较短的区间合并,所以要先处理出短的区间,j应在循环的外层
for(int j = ;( << j) <= n;j++)//1 << j 运用了位运算,代表2^j
{
for(int i = ;( << j) + i - <= n;i++)//dp[i][j]覆盖的区间为[i, (1 << j) + i - 1]
{
dp[i][j] = max(dp[i][j - ], dp[i + ( << (j - ))][j - ]);//状态转移方程,书写这里时要注意位运算符的优先级
}
}
}
2、查询
为了保证查询的准确性,待查区间一定要被预处理出来的区间恰好覆盖。实现这一点,只需要两段长度小于待查区间的且长度为2的幂的区间即可。例如区间[1, 5]可以用[1, 4]和[2, 5]来覆盖。
如果待查区间长度为len的话,我们只需要查询长度为2^
的两段区间就可以了(注意log得到的结果这里向下取整了)。
int ask(int l, int r)//查询[l, r]中的最大值
{
int len = r - l + , k = ;//len为待查区间长度
while( << (k + ) <= len)
k++;
//k代表原区间可以由两段长为2^k的区间覆盖
return max(dp[l][k], dp[r - ( << k) + ][k]);
}
动态规划——稀疏表求解RMQ问题的更多相关文章
- 算法学习 - ST表 - 稀疏表 - 解决RMQ问题
2017-08-26 21:44:45 writer:pprp RMQ问题就是区间最大最小值查询问题: 这个SparseTable算法构造一个表,F[i][j] 表示 区间[i, i + 2 ^ j ...
- 基于稀疏表(Sparse Table)的RMQ(区间最值问题)
在RMQ的其他实现方法中,有一种叫做ST的算法比较常见. [构建] dp[i][j]表示的是从i起连续的2j个数xi,xi+1,xi+2,...xi+2j-1( 区间为[i,i+2j-1] )的最值. ...
- RMQ (Range Minimal Query) 问题 ,稀疏表 ST
RMQ ( 范围最小值查询 ) 问题是一种动态查询问题,它不需要修改元素,但要及时回答出数组 A 在区间 [l, r] 中最小的元素值. RMQ(Range Minimum/Maximum Query ...
- [TJOI2017] DNA - 后缀数组,稀疏表
[TJOI2017] DNA Description 求模式串与主串的匹配次数,容错不超过三个字符. Solution 枚举每个开始位置,进行暴力匹配,直到失配次数用光或者匹配成功.考虑到容错量很小, ...
- POJ 3264 Balanced Lineup 【ST表 静态RMQ】
传送门:http://poj.org/problem?id=3264 Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total S ...
- ST表解决RMQ问题
RMQ问题: RMQ(Range Minimum/Maximum Query),区间最值查询.对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j之间 ...
- ST表 求 RMQ(区间最值)
RMQ即Range Minimum/Maximun Query,中文意思:查询一个区间的最小值/最大值 比如有这样一个数组:A{3 2 4 5 6 8 1 2 9 7},然后问你若干问题: 数组A下标 ...
- ACM/ICPC 之 暴力打表(求解欧拉回路)-编码(POJ1780)
///找到一个数字序列包含所有n位数(连续)一次且仅一次 ///暴力打表 ///Time:141Ms Memory:2260K #include<iostream> #include< ...
- ST表(离线RMQ)
离线RAQ时,预处理为O(n*lgn),查询为O(1)的算法,比较有意思的一种算法 放个模板在这可以随时看 //ST表(离线) //预处理 O(n*lgn) , 查询 O(1) #include &l ...
随机推荐
- 有用的2个 Windows 下批处理文件(bat文件):
创建多个文件夹(目录): 新建一个记事本:win + R –>输入notepad 在笔记本中输入如下: mkdir Would mkdir you mkdir marry mkdir me 另存 ...
- P2617 Dynamic Rankings(待修改区间第k大)
题目链接:https://www.luogu.org/problemnew/show/P2617 题目: 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的 ...
- 免插件,简单实现上拉加载loading
上拉加载是前端经常遇到的问题,采用插件往往能够轻松解决,这里介绍一种免插件简单实现上拉加载的方法,参考一下,下面分享一下代码. html <body> <ul> <li& ...
- vue大文件分片上传插件
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
- [POJ 1911] 棋盘
问题描述 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着 ...
- 小A与最大子段和 斜率优化 + 二分 + 细节
Code: #include <bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) ...
- SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6]
SLF4J:你的SLF4J绑定请求的1.6版不兼容[1.5.5,1.5.6] 在lib中,此时slf4j的版本是1.5.6,而slf4j-log4j的版本是1.6.由于版本的不兼容性,导致了这个错误. ...
- win7系统开机启动出现蓝屏,提示BAD_SYSTEM_CONFIG_INFO
因为我在msconfig->引导->高级选项中将最大内存勾选,最大内存勾选后是4096MB,但是在点击确定按钮后,会自动变成0MB(点击确定按钮后再点击高级选项),导致系统无法识别内存,开 ...
- jQuery FileUpload doesn't trigger 'done'
https://stackoverflow.com/questions/14674999/jquery-fileupload-doesnt-trigger-done If your server ...
- PHP不使用内置函数intval(),实现字符串转整数
平时我们用PHP时,将字符串转化为整型时,一般都是使用 intval() 内置函数,那么如果我们自己写,怎么写一个呢? 此时我们可以利用 ASCII 码计算得整数的特性,因为每个字符都对应一个 ASC ...