一:引入
RMQ是求某个区间内的最大值或最小值。
RMQ的求解方法-----ST算法
二:ST算法
ST算法利用了动态规划。这里假设有arr[1..n]一组数,设f[i][j]表示从 a[i]a[i+(2^j)-1] 的最大值,也就是以a[i]为起点的连续2^j个数的最大值。由于数个数有2^j个,所以从中间平均分为两部分,每一部分的数的个数为2^(j-1)个。
动态规划最优化原理。所以,我们可以得到这样的一个状态转移方程:f[i][j]=max(f[i][j-1] , f[i+2^(j-1)][j-1],边界为

2.询问:
若我们要询问区间[L,R]的最大值,那么,我们需要先求出最大的x满足2^x <=R-L+1,那么区间[L,R]的最大值便是


三:一点小技巧
因为cmath中的log2的函数效率不高,所以,还是自己写吧。
四:代码
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+10; int f[maxn][25],a[maxn],n,m,x,Log[maxn],y; int main() { scanf("%d%d",&n,&m);//n代表序列长度,m代表询问次数; for(int i=1;i<=n;++i){scanf("%d",&a[i]);f[i][0]=a[i];}//预处理; Log[0]=-1;//初始化一下; for(int i=1;i<=n;++i) { Log[i]=Log[i/2]+1;//用一下小技巧; } for(int j=1;j<=22;++j) for(int i=1;i+(1<<j)-1<=n;++i) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);//动态规划公式运用; for(int i=1;i<=m;++i) { scanf("%d%d",&x,&y); int s=Log[y-x+1];//算出上文所说的x的值 printf("%d\n",max(f[x][s],f[y-(1<<s)+1][s]));//比较大小,输出; } }
五:总结
ST是一个很好理解的算法。。。如果不懂,多看几遍其实就会了大半了。。。
文章来源: RMQ问题