P15100 [ICPC 2025 LAC] Festival Signs 题解

题意

给出一个数轴,数轴包含非整数的点,最初所有点的点权 \(w\)\(0\),现在有一些操作:

  • + l r h 表示向数轴上 \([l,r]\) 中的所有点的 \(w_i=\max(h,w_i)\)
  • - x 表示撤销第 \(x\)+ l r h 操作,保证这个操作没有被删除过。
  • ? l r 表示查询 \([l,r]\) 的最小点权。再次注意可以是非整数点,例如 \(1.5\)

题解

考虑线段树分治。我们先按照时间确定每个 + 操作存在的时间进行线段树分治。然后做一个区间取 \(\max\),区间查 \(\min\) 的线段树就好了,可以用类似标记永久化的思想简化代码。

然后为了使得这棵线段树可以进行原本的线段树分治操作,我们要记录线段树上所有点的修改来方便撤销。于是乎修改的时候记录一下就好了。注意数据范围,所以要离散化。

关于非整数点的操作,我们让离散化后所有点的下标 \(\times 2\) 就好了,具体原因很好理解。

整体时间复杂度为 \(O(n\log^2n)\)

code:

#include<bits/stdc++.h>
#define fi first
#define se second
#define ls (p<<1)
#define rs (p<<1|1)
#define pb push_back
#define int long long
#define pii pair<int,int>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int N=5e5+10;
int n,m,k,T,a[N],tot,cnt,tmp,t[N<<4];
pii b[N],q[N],st[N<<6];
struct node{int l,r,h;}e[N];
vector<int> g[N<<2];
int idx(int x){return (lower_bound(a+1,a+tot+1,x)-a)*2;} 
void pushup(int p){
	st[++tmp]={p,t[p]};
	t[p]=max(t[p],min(t[ls],t[rs]));
}
void mak(int p,int l,int r,int x,int y,int h){
    st[++tmp]={p,t[p]};
    t[p]=max(t[p],t[p>>1]);
	if(x<=l&&r<=y){
		if(t[p]<h){
			st[++tmp]={p,t[p]};t[p]=h;
		}return;
	}int mid=(l+r)>>1;
    if(x<=mid) mak(ls,l,mid,x,y,h);
    if(y>mid) mak(rs,mid+1,r,x,y,h);
	pushup(p);	
}
int query(int p,int l,int r,int x,int y){
    st[++tmp]={p,t[p]};
    t[p]=max(t[p],t[p>>1]);
	if(x<=l&&r<=y){return t[p];}
    int mid=(l+r)>>1,res=INT_MAX;
	if(x<=mid) res=min(res,query(ls,l,mid,x,y));
    if(y>mid) res=min(res,query(rs,mid+1,r,x,y));
	return max(t[p],res);	
}
void dele(int x){
	per(i,tmp,x+1) t[st[i].fi]=st[i].se;
    tmp=x;
}
void upd(int p,int l,int r,int k){
	int x=b[k].fi,y=b[k].se;
	if(x<=l&&r<=y){
		g[p].pb(k);return;
	}int mid=(l+r)>>1;
	if(x<=mid) upd(ls,l,mid,k);
	if(y>mid) upd(rs,mid+1,r,k);
}
void solve(int p,int l,int r){
	int x=tmp;
	for(int v:g[p]){
		mak(1,1,tot,e[v].l,e[v].r,e[v].h);
	}if(l==r){
		if(q[l].fi) cout<<query(1,1,tot,q[l].fi,q[l].se)<<'\n';
		dele(x);return;
	}int mid=(l+r)>>1;
	solve(ls,l,mid);solve(rs,mid+1,r);
    dele(x);
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	rep(i,1,n){
		char c;cin>>c;
		if(c=='+'){
			int l,r,h;cin>>l>>r>>h;
			a[++tot]=l;a[++tot]=r;
			e[++cnt]={l,r,h};b[cnt].fi=i;
		}else if(c=='?'){
			int l,r;cin>>l>>r;
			a[++tot]=l;a[++tot]=r;
			q[i]={l,r};
		}else{
			int x;cin>>x;b[x].se=i;
		}
	}sort(a+1,a+tot+1);
	rep(i,1,cnt){
        if(b[i].fi&&b[i].se==0) b[i].se=n;
		e[i].l=idx(e[i].l);e[i].r=idx(e[i].r);
	}rep(i,1,n){
		if(q[i].fi){
			q[i].fi=idx(q[i].fi);q[i].se=idx(q[i].se);
		}
	}tot*=2;
    rep(i,1,cnt) upd(1,1,n,i);
	solve(1,1,n);
	return 0;
}
posted @ 2026-02-22 16:40  NeeDna  阅读(0)  评论(0)    收藏  举报