ST 表整体二分解法

整体二分时遍历数组从 \(mid\) 开始的最大值再合并就可以了,时间 \(O(n \log n + q)\) 空间 \(O(n)\)

#include<bits/stdc++.h>
//#define int long long
//#define lowbit(x) (x&-(x))
using namespace std;
const int maxn = 1e6+114;
int ans[maxn*5],a[maxn],lm[maxn],rm[maxn];
struct query{
	int l,r,id;
};
void solve(int l,int r,queue<query> &s){
	if(s.size()==0||l>r) return ;
	if(l==r){
		while(s.size()>0){
			ans[s.front().id]=a[l];
			s.pop();
		}
		return ;
	}
	int mid=(l+r)/2;
	queue<query> L,R,M;
	while(s.size()>0){
		int lt=s.front().l,rt=s.front().r;
		if(rt<=mid){
			L.push(s.front());
		}
		else if(lt>mid){
			R.push(s.front());
		}
		else{
			M.push(s.front());
		}
		s.pop();
	}
	solve(l,mid,L);
	solve(mid+1,r,R);
	lm[0]=a[mid];
	rm[0]=a[mid+1];
	for(int i=mid-1;i>=l;i--){
		lm[mid-i]=max(lm[mid-i-1],a[i]);
	}
	for(int i=mid+2;i<=r;i++){
		rm[i-mid-1]=max(rm[i-mid-2],a[i]);
	}
	while(M.size()>0){
		int lt=M.front().l,rt=M.front().r;
		ans[M.front().id]=max(lm[mid-lt],rm[rt-mid-1]);
		M.pop();
	}
}
int n,m;
queue<query> S;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
	query Q;
	cin>>Q.l>>Q.r;
	Q.id=i;
	S.push(Q);
}
solve(1,n,S);
for(int i=1;i<=m;i++){
	cout<<ans[i]<<'\n';
}
return 0;
}

posted @ 2024-02-12 00:36  ChiFAN鸭  阅读(17)  评论(0编辑  收藏  举报