【总结】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
",max(Max[l][a],Max[r-(1<<a)+1][a]));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/huixinxinw/p/12256781.html