1. 程式人生 > >資料結構—RMQ && LCA

資料結構—RMQ && LCA

1.ST演算法

解決RMQ[區間最值問題]的強力工具√;

即 Sparse Table 演算法,時間複雜度為O(nlogn)預處理+O(1)查詢;

預處理使用 DP 的思想,f(i, j)表示[i,i+2^{j}-1]區間中的最小值,即 f[i,j]表示從第 i 個數起連續 2^{j }個數中的最小值

假設要查詢從m到n這一段的最小值, 那麼我們先求出一個最大的k, 使得k滿足2^k<=(n-m+1),於是我們就可以把[m, n]分成兩個(部分重疊的)長度為2^{k}的區間.

至於為什麼查詢時左端點是r-2^k+1,

因為我們需要找到一個點x,使得x+2^{k}-1=r

這樣的話就可以得到x=r-2^k+1;

藍後類推另外一個√

模板用的洛谷的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;
}