資料結構—RMQ && LCA
阿新 • • 發佈:2018-12-13
1.ST演算法
解決RMQ[區間最值問題]的強力工具√;
即 Sparse Table 演算法,時間複雜度為O(nlogn)預處理+O(1)查詢;
預處理使用 DP 的思想,f(i, j)表示區間中的最小值,即 f[i,j]表示從第 i 個數起連續 個數中的最小值
假設要查詢從m到n這一段的最小值, 那麼我們先求出一個最大的k, 使得k滿足2^k<=(n-m+1),於是我們就可以把[m, n]分成兩個(部分重疊的)長度為的區間.
至於為什麼查詢時左端點是,
因為我們需要找到一個點x,使得
這樣的話就可以得到;
藍後類推另外一個√
模板用的洛谷的p3685
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<vector> #include<queue> #include<stack> #include<algorithm> #include<deque> #include<cmath> #include<cctype> #define LL long long #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 using namespace std; const int maxn=1000000+5; int n,m; int dp[maxn][20+1]; int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int query(int l,int r) { int k=log(r-l+1)/log(2); return max(dp[l][k],dp[r-(1<<k)+1][k]); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++)dp[i][0]=read(); for(int j=1;j<=21;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]); } } for(int i=1;i<=m;i++) { int l=read(),r=read(); printf("%d\n",query(l,r)); } return 0; }