数据结构—RMQ && LCA

版权声明:QAQ https://blog.csdn.net/priesty_/article/details/82938700

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;
}

猜你喜欢

转载自blog.csdn.net/priesty_/article/details/82938700
lca