1. 程式人生 > >[OI學習筆記]st表

[OI學習筆記]st表

pac 重復 ask 重疊 二維 round 處理 esp 開始

用來查詢區間最值(區間和,差等要處理重復部分)

下面均以以最大值為例

初始化 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 }

[OI學習筆記]st表