[OI學習筆記]st表
阿新 • • 發佈:2019-02-14
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 8void 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表