P3865 【模板】ST 表 && RMQ 问题 题解

思路

求区间最大值,一道ST表模板题。
没学过ST表的看这里。

当查询区间最值时,若只用暴力,肯定会超时,所以我们可以建造一个ST表,ST表可以先求出一些小的区间的最值,然后以此类推求出更大区间的最值,这样在查询的时候时间就会大大减少。

关于建表,我们举个例子,如果我们输入一个长度为 8 8 8 的数组,默认这一层为第 0 0 0 层,那么第一层的 1 到 7 1到7 17 个数,每个数是下面两个数的最值;第二层的 1 到 5 1到5 15 个数,每个数是下面两个数的最值;第一层的 1 1 1 个数,每个数是下面两个数的最值。

查询便是看当前区间的大小对应哪一层,在该层比较左边界的区间最值和右边界的最值即可。

代码如下

细节主要看代码,代码的注释会说的比较详细,这篇代码与上面所说的差不多,并且很简洁,很容易看懂。

#include 
using namespace std;
int n,m,l,r,a[20][100010];
int len;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)cin>>a[0][i];
	//建ST表 
	len=log2(n);//ST表的层数 
	for(int i=1;i<=len;i++){
		for(int j=1;j<=n-(1<<i)+1;j++){//第i层的区间大小是2的i次方即1<
			a[i][j]=max(a[i-1][j],a[i-1][j+(1<<i-1)]);//比较该层的一个区间的最值,即比较下面两个小区间的最值,下面区间的大小为1<
		}
	}
	//查询
	for(int i=1;i<=m;i++){
		scanf("%d%d",&l,&r);
		len=log2(r-l+1);//判断该区间应在哪一层找最值 
		int res=max(a[len][l],a[len][r-(1<<len)+1]);//判断该区间左边界的区间与右边界的最大值,如果该区间正好在整块之内,比较便毫无意义,不在反之,r-(1<
		printf("%d\n",res);
	}
	return 0;
}

你可能感兴趣的:(算法,数据结构)