天才的記憶(RMQ,ST表)
阿新 • • 發佈:2021-08-22
分析
裸的ST表
ST表
初始化
倍增枚舉出區間的最大值,f[N] [M]代表,從n開始長度為2^m的區間最值。
查詢
[l,r]
1.求出該區間長度最接近的倍增預處理後的長度,k = log(len)/log(2);
2.最大值為
\[Max=max(f[l][k],f[r-2^k+1][k]) \]ACcode
#include<bits/stdc++.h> using namespace std; const int N = 2e5 + 10,M = 18; int f[N][M]; int w[N]; int n,m; //初始化 void init() { for(int j=0;j<18;j++)//列舉區間長度 for(int i=1;i+(1<<j)-1<=n;i++)//列舉區間 { if(!j) f[i][j]=w[i];//如果區間長度為1,則就是它本身 else f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//否則,則最大值為[i,i+2^(j-1)]和[i+2^(j-1),i+2^j]中的最大值 } } int query(int l,int r) { int len = r-l+1; int k = log(len)/log(2);//從區間開頭,得到的最長的預處理的區間 return max(f[l][k],f[r-(1<<k)+1][k]);//這個區間的最大值,是[l,l+2^k],[r-2^k+1,r]中的最大值 } int main() { scanf("%d", &n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); init(); scanf("%d",&m); while (m -- ){ int l,r; scanf("%d%d",&l,&r); printf("%d\n",query(l,r)); } return 0; }