ST表

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\n",ans);
42     }
43     return 0;
44 }

 

posted @ 2019-10-02 20:34  毛炯人  阅读(148)  评论(0编辑  收藏  举报