[数据结构-查询区间最小值小结(RMQ问题(Range Minimum Query))]
来源:互联网 发布:杭州汉聚网络怎么样 编辑:程序博客网 时间:2024/04/29 01:40
查询区间第k大可以用划分树,而查询区间最小(最大)值可以用代码更简单的Sparse-Table(ST)算法(Tarjan发明)。
原理很简单,代码也很短:
令d(i,j)表示从i开始的,长度为2^j的一段元素最小值,那么可以用递推方法计算:
d(i,j) = min( d(i,j-1) , d(i+2^(j-1) , j-1) )
void RMQ_init(const vector<int>& A) { int n=A.size(); for(int i=0;i<n;i++) d[i][0]=A[i]; for(int j=1;(1<<j)<=n;j++) for(int i=0;i+(1<<j)-1<n;i++) d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);}
查询操作也很简单。查询区间[L,R]内最小值:令k为满足2^k<=R-L+1的最大整数,则以L开头、以R结尾的两个长度为2^k的区间合起来就覆盖了整个[L,R]区间。
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]);}
下面的代码预处理了mm数组,它表示k的值,所以速度更快:
const int MAXN = 50010;int dp[MAXN][20];int mm[MAXN];//初始化RMQ, b数组下标从1开始,从0开始简单修改void initRMQ(int n,int b[]){ mm[0] = -1; for(int i = 1; i <= n; i++) { mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1]; dp[i][0] = b[i]; } for(int j = 1; j <= mm[n]; j++) for(int i = 1; i + (1<<j) -1 <= n; i++) dp[i][j] = max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);}
0 0
- [数据结构-查询区间最小值小结(RMQ问题(Range Minimum Query))]
- 范围最小值查询 RMQ (Range Minimum Query)
- 范围最小值问题 (Range Minimum Query,RMQ)
- 范围最小值问题(Range Minimum Query,RMQ)
- Geeks - Range Minimum Query RMQ范围最小值查询
- RMQ (Range Minimum/Maximum Query)区间最值查询
- RMQ(Range Minimum Query)问题
- RMQ(Range Minimum/Maximum Query)问题
- RMQ(Range Minimum Query)问题
- RMQ (Range Minimum/Maximum Query)算法(查询区间最值)
- RMQ(Range Minimum Query)
- Range Minimum Query (RMQ)
- Range Minimum Query (RMQ)
- Range Minimum Query( RMQ )
- Range Minimum Query(RMQ)
- RMQ(Range Minimum Query)
- Range Minimum Query (RMQ)
- 算法 RMQ(Range Minimum Query)问题:Sparse-Table算法
- [dp专题-四边形不等式优化]51nod 1022
- [其它-GarsiaWachs算法]51nod 1023 石子归并v3
- [数据结构-划分树小结]
- 动态规划-美团笔试-字符串计数-恶心的dp
- [数据结构-树状数组小结]
- [数据结构-查询区间最小值小结(RMQ问题(Range Minimum Query))]
- hdu 4568 旅行商问题dp
- Linux命令——find
- POJ 2299 Ultra-QuickSort
- windows本地评测批处理脚本
- Linux下软链接与硬链接
- hdu4758 hdu2825 hdu4057 AC自动机与状态压缩dp的结合
- poj 2155 二维线段树
- CRC