【总结】st表

对于一类问题:

RMQ(Range Minimum/Maximum Query) 区间最值查询

给一个序列a[1],a[2],…,a[n],每次查询一个区间的最小值

我们可以用线段树解决,也可以一种更简单的数据结构st表来解决

st表相较于线段树而言时间复杂度更低,代码也更简洁

但是st表所能解决的问题非常有限

一句话总结就是:st表能解决的问题线段树一定能解决,但线段是能做到st表做不到

算法实现

运用倍增的思想,我们令\(f[i] [k]\)数组表示区间\([i,i + 2^k-1]\)中的最小值

\(f[i] [0]= a[i]\)

\(f[i] [k-1] = min(f[i] [k],f[i + (1<< k)] [k])\)

查询时给了一个区间[l, r],我们找一个最大的j满足\(2^j <= r - l + 1\)

于是我们可以用\(f[l] [j]\)\(f[r – 2^j + 1] [j]\)来覆盖这个区间,得到最小值

也即\(answer = min(f[l] [j], f[r – (1 << j) + 1] [j])\)

代码

#include<bits/stdc++.h>
using namespace std;
int n,m,l,r;//这是个st表emm可我不会 
int Max[100001][22];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&Max[i][0]);//读入emm他到他本身的区间最大值就是他w
	} 
	for(int j=1;j<=21;j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
		}
	}
	for(int i=1;i<=m;i++){
		scanf("%d%d",&l,&r);
		int a=log2(r-l+1);
		printf("%d\n",max(Max[l][a],Max[r-(1<<a)+1][a]));
	}
	return 0;
}
posted @ 2020-02-03 19:01  蕙心心w  阅读(129)  评论(0编辑  收藏  举报