#线段树,Beats#CF793F Julia the snail

题目传送门


分析

将询问按右端点升序排序,在线段树上维护 \(f_i\) 表示以 \(i\) 为起点能到达的最高的高度

那么右端点向右移动一格时,实际上是绳子 \((l,r)\) 在起作用,

此时如果 \(f_{1\sim l}\geq l\),那么就可以令这些 \(f\) 为 \(r\),此时涉及到 Beats,需要维护次大值。

如果 \(l\) 介于最大值和次大值之间就给这个区间打上 \(r\) 的懒标记,否则只要最大值能不小于 \(l\) 就继续递归下去。

不过由于最大值此时不会超过 \(r\) 所以,所以这个最大值组可以直接取 \(r\)。


代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N=100011,inf=0x3f3f3f3f;
struct node{int y,next;}e[N];
int a[N],as[N],ans[N],n,m,Q;
struct Segment_Tree{
	int mx[N<<2],semx[N<<2],lazy[N<<2];
	void pup(int k){
		if (mx[k<<1]==mx[k<<1|1])
			mx[k]=mx[k<<1],semx[k]=max(semx[k<<1],semx[k<<1|1]);
		else if (mx[k<<1]>mx[k<<1|1])
			mx[k]=mx[k<<1],semx[k]=max(semx[k<<1],mx[k<<1|1]);
		else mx[k]=mx[k<<1|1],semx[k]=max(mx[k<<1],semx[k<<1|1]);
	}
	void pdown(int k){
		if (!lazy[k]) return;
		int t=max(mx[k<<1],mx[k<<1|1]);
		if (mx[k<<1]==t) mx[k<<1]=lazy[k<<1]=lazy[k];
		if (mx[k<<1|1]==t) mx[k<<1|1]=lazy[k<<1|1]=lazy[k];
		lazy[k]=0;
	}
	void build(int k,int l,int r){
		lazy[k]=0;
		if (l==r){
			mx[k]=l,semx[k]=-inf;
			return;
		}
		int mid=(l+r)>>1;
		build(k<<1,l,mid);
		build(k<<1|1,mid+1,r);
		pup(k);
	}
	void update(int k,int l,int r,int x,int y,int L,int R){
		if (mx[k]<L) return;
		if (l==x&&r==y&&semx[k]<L){
			mx[k]=lazy[k]=R;
			return;
		}
		int mid=(l+r)>>1;
		pdown(k);
		if (y<=mid) update(k<<1,l,mid,x,y,L,R);
		else if (x>mid) update(k<<1|1,mid+1,r,x,y,L,R);
			else update(k<<1,l,mid,x,mid,L,R),update(k<<1|1,mid+1,r,mid+1,y,L,R);
		pup(k);
	}
	int query(int k,int l,int r,int x){
		if (l==r) return mx[k];
		int mid=(l+r)>>1;
		pdown(k);
		if (x<=mid) return query(k<<1,l,mid,x);
			else return query(k<<1|1,mid+1,r,x);
	}
}Tre;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for (int i=1;i<=m;++i){
		int x,y; cin>>x>>y;
		a[y]=x;
	}
	cin>>Q;
	for (int i=1;i<=Q;++i){
		int x,y; cin>>x>>y;
		e[i]=(node){x,as[y]},as[y]=i;
	}
	Tre.build(1,1,n);
	for (int i=1;i<=n;++i){
		if (a[i]) Tre.update(1,1,n,1,a[i],a[i],i);
		for (int j=as[i];j;j=e[j].next)
			ans[j]=Tre.query(1,1,n,e[j].y);
	}
	for (int i=1;i<=Q;++i) cout<<ans[i]<<'\n';
	return 0;
}
posted @ 2026-09-28 17:04  lemondinosaur  阅读(12)  评论(0)    收藏  举报