动态规划——稀疏表求解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 ...
随机推荐
- Codeforces Round #421 (Div. 2) - B
题目链接:http://codeforces.com/contest/820/problem/B 题意:给定一个正n边形,然后让你选择3个不同的顶点,使得这3个顶点形成的角度尽可能的接近a. 思路:首 ...
- css图像拼合技术(精灵图)
CSS图像拼合技术 1.图像拼合 图像拼合技术就是单个图像的集合. 有很多图片的网页可能会需要很多时间来加载和生成多个服务器的请求. 使用图像拼合会降低服务器的请求数量,并节省带宽. 图像拼合实例 有 ...
- 【leetcode】885. Boats to Save People
题目如下: 解题思路:本题可以采用贪心算法,因为每条船最多只能坐两人,所以在选定其中一人的情况下,再选择第二个人使得两人的体重最接近limit.考虑到人的总数最大是50000,而每个人的体重最大是30 ...
- 对calc()的研究
1.calc是英文单词calculate(计算)的缩写,是css3的一个新增的功能,用来指定元素的长度 calc()最大的好处就是用在流体布局上 2.calc()使用通用的数学运算规则 使用“+”.“ ...
- linux运维、架构之路-内网NTP时间服务器
一.环境 [root@m01 tmp]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@m01 tmp]# hostname -I ...
- Android多线程方案
为主线程减轻负的多线程方案有哪些呢?这些方案分别适合在什么场景下使用? Android系统为我们提供了若干组工具类来帮助解决这个问题. AsyncTask: 为UI线程与工作线程之间进行快速的切换提供 ...
- 20180805-Java DataInputStream类
DataInputStream dis = DataInputStream(InputStream in); 下面的例子演示了DataInputStream和DataOutputStream的使用,该 ...
- mysql中 key 、primary key 、unique key 和 index 有什么不同
mysql中 key .primary key .unique key 和 index 有什么不同 key 是数据库的物理结构,它包含两层意义和作用, 一是约束(偏重于约束和规范数据库的结构完整性), ...
- BaseActivity 基类
public abstract class BaseActivity extends AppCompatActivity implements IBaseView { private ProxyAct ...
- MYSQL之union和order by分析([Err] 1221 - Incorrect usage of UNION and ORDER BY)
我在一个业务中采用了按月的分表策略,当查询的条件跨月的时候,使用了union all汇总2个表的数据,并按插入时间倒序排列.查询并不复杂,但是当执行的时候却报错了. SELECT * FROM `ta ...