算法學習——st表
阿新 • • 發佈:2018-09-15
合並 什麽 沒有 mes 怎麽 空格 mage info int
st表是一種基於倍增思想的DP。
用於求一個數列中的某個區間的最大/最小值。
用st[i][j]表示從第i個開始往後2^j個點,最大的是多少。
我們令k[i]表示2^i等於多少
那麽有轉移方程
st[i][j] = max(st[i][j - 1], st[i + k[i - 1]][j - 1]);
為什麽呢?
例如這幅圖,顯然黑色塊的答案可以由合並下面兩塊得到。
那如果查詢的時候不是2的整次冪怎麽辦?
這其實是沒有問題的,你可以觀察下圖……
因為小區間有重疊部分並不影響,因此完全可以用稍大一點的小區間湊出大區間。
預處理一點信息以快速查詢答案即可。
(早期代碼,沒有空格空行,略醜)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,s[100500],f[100500][18],p[100500]; 4 int Max(int a,int b) 5 { 6 if(a>b)return a; 7 else return b; 8 } 9 int Min(int a,int b) 10 { 11 if(a<b)return a; 12 else return b; 13 } 14 void pre()15 { 16 int i,a,key=1; 17 for(i=1;i<=n;i++) 18 { 19 if(i==(key<<1))p[i]=p[i-1]+1,key<<=1; 20 else p[i]=p[i-1]; 21 scanf("%d",&a); 22 f[i][0]=a; 23 } 24 for(int j=1;j<=17;j++) 25 for(i=1;i<=n;i++) 26 {27 f[i][j]=Max(f[i][j-1],f[Min(i+(1<<(j-1)),n)][j-1]); 28 } 29 } 30 int main() 31 { 32 int i,a,b,k; 33 scanf("%d%d",&n,&m); 34 pre(); 35 for(i=1;i<=m;i++) 36 { 37 scanf("%d%d",&a,&b); 38 k=p[b-a+1]; 39 printf("%d\n",Max(f[a][k],f[b-(1<<k)+1][k])); 40 } 41 return 0; 42 }
算法學習——st表