[OI学习笔记]st表

用来查询区间最值(区间和,差等要处理重复部分)

下面均以以最大值为例

初始化 0(nlogn)

设st[i][k]为下标i开始的2k个元素的最值

则: st[i][k]=max{st[i][k-1],st[i+2k-1][k-1]}

即区间[i,i+2k -1]的前一半和后一半的最值取最大

查询 O(1)

对于区间[l,r],区间长度len=r-l+1;找到满足2p <=len的最大p

最大值ans=max{st[l][p],st[r-2p +1][p]} 

显然,当2p !=len时,区间[l,l+p-1]和[r-2p +1][r]有重叠

这也是为什么前面说区间和,差等要处理重复部分。

2p <=len的p的最大值p <=log2len

p=⌊log2len⌋  (下取整)

代码:

(感谢XLightGod(THU巨佬)指正我的错误,第12行下标范围是i+(1<<k)-1<=n)

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cmath>
 4 using namespace std;
 5 
 6 int a[10010],st[10010][21],n;//st的第二维取到log2(10010)即可 
 7 
 8 void init(){
 9     for(int i=0;i<=n;i++)
10         st[i][0]=i;
11     for(int k=1;(1<<k)<=n;k++)
12         for(int i=1;i+(1<<k)-1<=n;i++)
13             st[i][k]=max(st[i][k-1],st[i+(1<<(k-1))][k-1]);
14             
15 }
16 
17 int ask(int l,int r){
18     int len=r-l+1;
19     int p=(int)log((double)(len))/log(2.0);//满足2^p<=r-l+1的最大p
20     return max(st[l][p],st[r-(1<<p)+1][p]); 
21 }
22 
23 //以最大值为例 
24 int main(){
25     scanf("%d",&n);
26     for(int i=1;i<=n;i++)
27         scanf("%d",&a[i]);
28     init();
29     while(1){
30         int l,r;
31         scanf("%d",&l);
32         if(l==-1)exit(0);
33         scanf("%d",&r);
34         int ans=ask(l,r);
35         printf("%d\n",ans);
36     }
37     return 0;
38 } 

猜你喜欢

转载自www.cnblogs.com/sjrb/p/10375723.html
今日推荐