RMQ與st表
阿新 • • 發佈:2018-07-22
ref sts 基本上 ble esp code inline urn print
模板題
P3865 【模板】ST表
代碼
實質也是DP,利用倍增獲取從i開始長度為\(2^0,2^1,2^2…2^j\)的區間內的最大值。
這樣對於任意區間\([l,r]\)都有,令\(dis=r-1+1\)則有\(k_0=2^c,2^{k_0}≤dis≤2^{k_0+1}\)這樣在區間\([l,l+k0-1],[r-k0+1,r]\)完全覆蓋了這個區域(中間可能有重疊)
#include <iostream> #include <cmath> #include <cstdio> using namespace std; int dp[100100][20]; int a[100100]; int lg[100100]; int n,m; void st(){ for(int i=1;i<=n;i++){ dp[i][0]=a[i]; } for(int j=1;(1<<j)<=n;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]); } } // 方法2 // int k=0; // for(int i=1;i<=n;i++){ // if(i<=(1<<(k))){ // lg[i]=k; // }else{ // k++; // lg[i]=k; // } // } } int RMQ(int l,int r){ int k=0; // 方法2 // k=lg[r-l+1]-1; // 方法3 // while((1<<(k+1))<=r-l+1){ // k++; // } // 方法1 k=(double)log(r-l+1)/log(2); return max(dp[l][k],dp[r-(1<<k)+1][k]); } void init(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } } int main(){ init(); st(); // cout<<RMQ(1,5); int q,w; for(int i=1;i<=m;i++){ scanf("%d%d",&q,&w); printf("%d\n",RMQ(q,w)); } }
計算log的方法可以提前用O(n)的預處理(方法2)或者每次lgn的計算(常數很小,基本上可以忽略)或者不知道常數的。。log算法
反正從代碼上來看時間,log\(<\)預處理\(<\)\(O(lgn)\)計算
分別是1112ms 1224ms 1648ms
洛谷評測
RMQ與st表