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;
}

浙公网安备 33010602011771号