版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
ST算法的算法的实质是倍增的产物。今天我们想以RMQ为例,介绍ST算法。
RMQ
题目:给定一段区间,用O(1)的时间复杂度访问(l,r)的最大值
输入:
10
1 2 45 7 4 1 126 1 45 7
5
1 1
1 5
2 3
4 7
6 7
输出:
1
45
45
126
126
我们先上代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1010;
int n;
int f[N][N],d[N];
void work(){
for(int i=1;i<=n;i++) f[i][0]=d[i];
int t=log(n)/log(2)+1;
for(int j=1;j<t;j++)
for(int i=1;i<=n-(1<<j)+1;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int query(int l,int r)
{
int k=log(r-1+1)/log(2);
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int main(){
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) cin>>d[i];
work();//预处理
int T;
cin>>T;
while(T--)
{
int l,r;
cin>>l>>r;
cout<<query(l,r)<<endl;
}
return 0;
}
这道题有点像动态规划,我们用f[i][j]表示[i,i+2j-1]的状态,我们把这些状态枚举一遍,注意c++里面的log方法是求ln,我们用换底公式变成求log,动态规划的状态转移方程的意思是f[i][j]的max要么是出现在[i,i+2(j-1)-1]要么出现在[i+2j-1,i+2j-1]就是这样,然后我们说说查询,原理比较简单,和状态转移类似,就是会出现重复区间,但是不要怕,只要不越界,重复区间不会影响我们的结果。