ST表通常用于解决RMQ问题,支持的事静态查询区间的最值,不可修改。
其中建表的时间复杂度是O(nlgn),查询则是O(1)。
这里ST表其实用到了动态规划以及而分的思想,把每一个区间二分至自己是区间的最值,然后逐步进行比较,然后进行查询即可。首先我们建立一个st[][],用来存储从第i个开始,往后2^j个数的最大值。在这之前,我们要进行一个对数运算(当然还要明白位运算,1<<j等同于2^j),把以二为底i的对数求出来,方便下面计算长度。然后就去写函数,推出f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
表示从i 到 2^(j-1)-1与 i+2^(j-1)到i+2^j的最大值。最后进行查询的时候,我们不能直接输出st[l][r],所以我们要先求出2的k次方等于r-l+1,然后分别求出i,i+2^k和r-i^k,r的最大值,这样就可以保证都访问过了,重复也无关于求最值。
代码
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define M 25 5 #define N 100005 6 using namespace std; 7 int n,m; 8 int a[N],Log[N]; 9 int f[N][M]; 10 int l,r; 11 void GetLog() 12 { 13 Log[1]=0; 14 for(int i=2;i<=n+1;i++) 15 Log[i]=Log[i/2]+1; 16 } 17 void RMQ() 18 { 19 for(int i=1;i<=n;i++) 20 f[i][0]=a[i]; 21 for(int j=1;(1<<j)<=n;j++){ 22 for(int i=1;i+(1<<(j-1))<=n;i++){ 23 //[i,i+2^{j-1}-1] & [i+2^{j-1},i+2^{j} -1] 24 f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); 25 } 26 } 27 } 28 int k,ans; 29 int main() 30 { 31 scanf("%d%d",&n,&m); 32 for(int i=1;i<=n;++i) 33 scanf("%d",&a[i]); 34 GetLog(); 35 RMQ(); 36 for(int i=1;i<=m;++i) 37 { 38 scanf("%d%d",&l,&r); 39 int k=Log[r-l+1]; 40 ans=max(f[l][k],f[r-(1<<k)+1][k]); 41 printf("%d ",ans); 42 } 43 return 0; 44 }