动态规划——稀疏表求解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 ...
随机推荐
- vue.js(18)--父组件向子组件传值
子组件是不能直接使用父组件中数据的,需要进行属性绑定(v-bind:自定义属性名=“msg”),绑定后需要在子组件中使用props[‘自定义属性名’]数组来定义父组件的自定义名称. props数组中的 ...
- Altium Designer设计PCB中如何开槽
在不同层画槽孔形状实际得到的PCB效果(注意槽孔边缘) 在不同层画槽孔形状进行(注意槽孔边缘) 很多坛友问在使用Altium Designer设计PCB时,想在板子上开一个槽或者挖一个孔该如何操作,是 ...
- Windows 进入上帝模式窗口
Win10上帝模式如何启用? 默认情况下,Win10的上帝模式是隐藏的,如果要开启的话,操作步骤也非常简单,下面就介绍两种方法. 方法一.直接运行命令行 1.使用[Win + R ]快捷键打开“运行” ...
- 去掉Tomcat网站地址栏的小猫图标
当我们打开CSDN等网站时,在地址栏前面就会出现红色的C状图标,如果在桌面新建此链接的快捷方式,则桌面图标也自动变为该地址栏ICO图标.在基于TOMCAT的BS应用或网站开发时,默认的图标为黄色的小猫 ...
- Intellij IDEA 插件开发秘籍
来这里找志同道合的小伙伴! 这里总结一下 Intellij IDEA 插件开发的知识,供大家参考,本篇文章包含以下内容: 开发环境搭建 Component 介绍 Extension Point And ...
- tuple写法
name = ("wen") 类型为strname = ("wen",) 类型为tuple
- 传统IO拷贝与零拷贝技术比较
1. 传统IO 由上面图知,传统io需要经过4次copy, 3次状态切换 第一次: 从硬盘 经过 DMA 拷贝 到 kernel buffer (内核buferr) 第二次: 从kernel buff ...
- 破解Revealapp的试用时间限制
转载自:http://jingwei6.me/2014/02/28/reveal_crack.html Revealapp作为分析iOS app UI结构的利器,还是非常称手的,89刀的价格也是物有所 ...
- php 标准库之ArrayObject
以下为ArrayObject的常用函数: ArrayIterator::current( void ) //返回当前数组元素 ArrayIterator::key(void) //返回当前数组key ...
- POJ 2653 Pick-up sticks(几何)
Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13377 Accepted: 5039 D ...