RMQ(范围最小化问题)【倍增法】
程序员文章站
2024-03-22 13:51:34
...
问题描述
范围最小化问题(Range Minimum Query,RMQ)。给出一个 n
个元素的数组 ,设计一个数据结构,支持查询 Query(L, R):
计算 。
解题报告
令 表示从 开始的,长度为 的一段元素中的最小值,则可以用递推的方式计算 。
为什么 dp[i][j]
表示的是 从 开始的,长度为 的一段元素中最小值呢?
如果这样的话,就需要在三个区间中找最小值,一方面状态转移方程不好写,另一方面,时间复杂度和空间复杂度并没有提升多少,所以是 。
注意到 ,因此 d
数组的元素个数不超过 ,而每一项都可以在常数时间计算完毕,故总时间为
查询操作很简单,令 k
为满足 的最大整数,则以 开头、以 结尾的两个长度为 的区间合起来覆盖了查询区间 。由于是取最小值,有些元素重复考虑了几遍也没有关系。
实现代码
- 预处理
void RMQ_INIT(const vector<int>&A){
int n= A.size();
for(int i=0;i<n;i++)dp[i][0]=A[i];
for(int j=1;(1<<j)<=n;j++){
for(int i=0;i+(1<<j)-1<n;i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1])
}
}
- 查询
int RMQ(int l, int r){
int k=0;
while((1<<(k+1))<=r-l+1) k++;
return min(d[l][k], d[r-(1<<k)+1][k])
}
参考资料
[1] 算法竞赛·入门经典·训练指南 P197.
上一篇: ETL工具之——kettle使用简介