st表能夠\(nlogn\)預處理,O1查詢,相對於線段樹的logn查詢相對有優點,可是st表只能支持靜態解決RMQ,這是一個很是大的劣勢。html
ST表是利用的是倍增的思想ios
拿最大值來講spa
咱們用𝑀𝑎𝑥[𝑖][𝑗]Max[i][j]表示,從𝑖i位置開始的2𝑗2j個數中的最大值,例如𝑀𝑎𝑥[𝑖][1]Max[i][1]表示的是𝑖i位置和𝑖+1i+1位置中兩個數的最大值code
那麼轉移的時候咱們能夠把當前區間拆成兩個區間並分別取最大值(注意這裏的編號是從11開始的)htm
查詢的時候也比較簡單blog
咱們計算出𝑙𝑜𝑔2(區間長度)log2(區間長度)get
而後對於左端點和右端點分別進行查詢,這樣能夠保證必定能夠覆蓋查詢的區間string
剛開始學的時候我不太理解爲何從右端點開始查的時候左端點是𝑟−2𝑘+1r−2k+1it
實際很簡單,由於咱們須要找到一個點𝑥x,使得𝑥+2𝑘−1=𝑟x+2k−1=rio
這樣的話就能夠獲得𝑥=𝑟−2𝑘+1
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<sstream> #include<queue> #include<map> #include<vector> #include<set> #include<deque> #include<cstdlib> #include<ctime> #define dd double #define ll long long #define ld long double #define ull unsigned long long #define N 100010 #define M number using namespace std; const int INF=0x3f3f3f3f; int n,m,a[N]; int sum[N][50]; inline int Min(int a,int b){ return a>b?b:a; } inline int Max(int a,int b){ return a>b?a:b; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); // memset(sum,INF,sizeof(sum)); for(int i=1;i<=n;i++) sum[i][0]=a[i]; for(int i=1;(1<<i)<=n;i++) for(int j=1;j+(1<<i)-1<=n;j++) sum[j][i]=Max(sum[j][i-1],sum[j+(1<<(i-1))][i-1]); for(int i=1;i<=m;i++){ int l,r; scanf("%d%d",&l,&r); int k=log2(r-l+1); int minn=Max(sum[l][k],sum[r-(1<<k)+1][k]); printf("%d\n",minn); } }