st表復習筆記
阿新 • • 發佈:2019-05-04
\n 線段樹 問題 ostream 常數 com using ++ 開始
st表,一種高效的區間最值查詢(RMQ)算法。本質其實是一個動態規劃。
其實吧,對於看過線性dp的人來說應該不難理解,只是處理有些麻煩。但是本土狗因為-1的問題居然改了許久...
用兩個2^i的區間把整個區段覆蓋,dp[i][j]表示區間最值,從i開始,向前2^j個數字。根據動態規劃的定義,把這個區間分割成兩個小區間,於是就有
dp[i][j]=max(dp[i][j-1],dp[i][i+(1<<j-1)]);(然而我在這裏處理區間的時候多減了一個1....)
一直分割下去,直到1。復雜度O(nlogn)。
於是查詢:
我們找到左右區間大小(y-x+1),把它log一下,再2的次方一下,就成了覆蓋區間的最大2^i次方的區間。同理,右區間也是。比較兩區間最值,就可以得出最值了。
code:
#include<iostream> #include<cstdio> using namespace std; const int maxn=100005; int n,m,a[maxn],dp[maxn][25],l[maxn]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } l[0]=-1; for(int i=1;i<=n;++i) { dp[i][0]=a[i]; l[i]=l[i>>1]+1; } for(int j=1;j<=25;++j) { for(int i=1;i+(1<<j)-1<=n;++i) { dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); int s=l[y-x+1]; printf("%d\n",max(dp[x][s],dp[y-(1<<s)+1][s])); } return 0; }
類比線段樹:
優點:
1、碼量小
2、快(不用說了,線段樹常數大得呦...)
缺點:
1、只能靜態
2、只能最值
(完)
st表復習筆記