st表

链接:https://www.luogu.com.cn/problem/P3865

倍增思想
st[i][j] 表示 \([i,i+2^j-1]\) 内的最大/最小值
倍增更新

\[st[i][j] = max\{st[i][j-1],st[i+2^j][j-1]\} \]

查询的时候找到左右端点,找到两段区间将[l,r]覆盖

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 200010;

int n,m;
ll a[maxn],sta[maxn][22],sti[maxn][22];

ll qry(int l,int r){
	int k = 0;
	while((1<<(k+1))<=(r-l+1)) ++k;
	return max(sta[l][k],sta[r-(1<<k)+1][k]);
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	n = read(),m = read();
	
	for(int i=1;i<=n;++i) a[i] = read(), sta[i][0] = sti[i][0] = a[i];
	
	for(int j=1;(1<<j)<=n;++j){
		for(int i=1;i<=n;++i) {
			sta[i][j] = max(sta[i][j-1], sta[i+(1<<j-1)][j-1]);
			sti[i][j] = min(sti[i][j-1], sta[i+(1<<j-1)][j-1]);
		}
	}

	for(int i=1;i<=m;++i){
		int l,r;
		l = read(), r = read();
		printf("%lld\n",qry(l,r));
	}
	
	return 0;
}
posted @ 2020-10-18 10:15  Tartarus_li  阅读(66)  评论(0编辑  收藏  举报