1. 程式人生 > 實用技巧 >2020團體程式設計天梯賽

2020團體程式設計天梯賽

ST表的功能很簡單

它是解決RMQ問題(區間最值問題)的一種強有力的工具

它可以做到O(nlogn)預處理,O(1)查詢最值

ST表是利用的是倍增的思想

拿最大值來說

我們用Max[i][j]表示,從i位置開始的2j個數中的最大值,例如Max[i][1]表示的是i位置和i+1位置中兩個數的最大值

那麼轉移的時候我們可以把當前區間拆成兩個區間並分別取最大值(注意這裡的編號是從1開始的)

查詢的時候也比較簡單

我們計算出log2()

然後對於左端點和右端點分別進行查詢,這樣可以保證一定可以覆蓋查詢的區間

剛開始學的時候我不太理解為什麼從右端點開始查的時候左端點是r2k+1

實際很簡單,因為我們需要找到一個點

x,使得x+2k1=r

這樣的話就可以得到x=r2k+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; }