#线段树,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;
}

浙公网安备 33010602011771号