2020團體程式設計天梯賽
阿新 • • 發佈:2020-12-06
ST表的功能很簡單
它是解決RMQ問題(區間最值問題)的一種強有力的工具
它可以做到O(nlogn)預處理,O(1)查詢最值
ST表是利用的是倍增的思想
拿最大值來說
我們用Max[i][j]表示,從i位置開始的2j個數中的最大值,例如Max[i][1]表示的是i位置和i+1位置中兩個數的最大值
那麼轉移的時候我們可以把當前區間拆成兩個區間並分別取最大值(注意這裡的編號是從1開始的)
查詢的時候也比較簡單
我們計算出log2(區間長度)
然後對於左端點和右端點分別進行查詢,這樣可以保證一定可以覆蓋查詢的區間
剛開始學的時候我不太理解為什麼從右端點開始查的時候左端點是r−2k+1
實際很簡單,因為我們需要找到一個點 x,使得x+2k−1=r
這樣的話就可以得到x=r−2k+1
上面講的可能比較抽象,建議大家畫個圖好好理解一下
程式碼:
#include <bits/stdc++.h> using namespace std; const int MAXN=1e6+10; int Max[MAXN][21]; int Query(int l,int r) { int k=log2(r-l+1); return max(Max[l][k],Max[r-(1<<k)+1][k]);//把拆出來的區間分別取最值 } void st(int N) { for(int i=1;i<=N;i++) cin>>Max[i][0]; for(int j=1;j<=21;j++) //也可寫成(1 << j) <= N for(int i=1;i+(1<<j)-1<=N;i++)//注意這裡要控制邊界 也可寫成(1 << j) <= N Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);//如果看不懂邊界的話建議好好看看圖 } int main() { int N,M; cin>>N>>M; st(N);for(int i=1;i<=M;i++) { int l,r; cin>>l>>r; printf("%d\n",Query(l,r)); } return 0; }