题解 P7549【[BJWC2017] 神秘物质】

· · 题解

\text{Link}

在校内 \text{OJ} 看到的一道题,在 \text{Luogu} 找到了,发现没有题解,于是来写一个。

sto zltzlt orz.

题意

给你一个序列 a,支持 4 个操作:

## 思路 看到插入、删除就可以想到使用文艺平衡树来解决问题,这里我使用 $\text{Splay}$,操作 $1,2$ 十分显然。 $3$ 操作可以直接维护区间的最大值和最小值,答案就是它们做差。 $4$ 操作中,我们设答案的子区间为 $[l',r']$,设其中最大值为 $a$,最小值为 $b$,若区间中加入一个数 $v$,则 $a\gets \max(a,v),b\gets\min(b,v),\max(a,v)-\min(b,v)\ge a-b$,即插入一个数显然不会更优,所以答案区间长度为 $2$。所以我们可以维护每个数与其左右的差的绝对值,分别设为 $lb_x,rb_x$,再维护 $ms_x$ 代表 $x$ 子树内 $lb,rb$ 的最小值,答案即为 $ms$。注意需要特判 $l+1=r$ 的情况,直接取 $rb_l$。 代码: ```cpp #include<bits/stdc++.h> using namespace std; #define ll long long namespace IO{//by cyffff } const int N=5e5+10,INF=1e9+10; int s[N]; int n,m; struct Splay{ #define ls a[x].son[0] #define rs a[x].son[1] int rt,sz; struct node{ int f,val,son[2],sz; int minn=INF,maxn,lb,rb,ms; inline void clear(){ f=maxn=son[0]=son[1]=val=sz=0; minn=ms=lb=rb=INF; } }a[N]; inline bool isr(int x){return a[a[x].f].son[1]==x;} inline void upd(int x){ node &p=a[x]; p.maxn=p.minn=p.val; p.ms=min(p.lb,p.rb); if(ls) p.maxn=max(p.maxn,a[ls].maxn),p.minn=min(p.minn,a[ls].minn),p.ms=min(p.ms,a[ls].ms); if(rs) p.maxn=max(p.maxn,a[rs].maxn),p.minn=min(p.minn,a[rs].minn),p.ms=min(p.ms,a[rs].ms); p.sz=a[ls].sz+1+a[rs].sz; } inline int newnode(int v){ sz++; a[sz].minn=a[sz].maxn=a[sz].val=v; return sz; } inline void rotate(int x){ int f=a[x].f,gf=a[f].f; int id=isr(x); a[f].son[id]=a[x].son[id^1]; a[a[f].son[id]].f=f; a[x].son[id^1]=f; a[f].f=x; a[x].f=gf; if(gf){ a[gf].son[a[gf].son[1]==f]=x; } upd(f); } inline void splay(int x,int goal=0){ goal=a[goal].f; for(int f;(f=a[x].f)!=goal;rotate(x)){ if(a[f].f!=goal){ rotate(isr(x)==isr(f)?f:x); } } if(!goal) rt=x; } inline int build(int l,int r,int f){ if(l>r)return 0; int mid=l+r>>1; sz++; int now=sz; a[now].f=f; a[now].val=s[mid]; a[now].lb=mid?abs(s[mid]-s[mid-1]):INF; a[now].rb=mid!=n+1?abs(s[mid]-s[mid+1]):INF; a[now].son[0]=build(l,mid-1,now); a[now].son[1]=build(mid+1,r,now); upd(now); return now; } inline int find(int x){ int now=rt; while(1){ if(x<=a[a[now].son[0]].sz){ now=a[now].son[0]; }else{ x-=a[a[now].son[0]].sz+1; if(!x){ return now; } now=a[now].son[1]; } } } inline int split(int l,int r){ int x=find(l); splay(x,rt); int y=find(r+2); splay(y,a[x].son[1]); return a[y].son[0]; } inline void MoMerge(int wz,int v){ int x=split(wz,wz+1),f=rt,y=a[f].son[1]; a[x].val=v; if(ls) a[ls].clear(),ls=0; if(rs) a[rs].clear(),rs=0; a[f].rb=a[x].lb=abs(v-a[f].val); a[x].rb=a[y].lb=abs(v-a[y].val); upd(x),upd(y),upd(f); } inline void MoInsert(int wz,int v){ int x=split(wz,wz),f=rt,y=a[f].son[1],z=newnode(v); a[z].f=x; a[x].son[1]=z; a[x].rb=a[z].lb=abs(v-a[x].val); a[z].rb=a[y].lb=abs(v-a[y].val); upd(z),upd(x),upd(y); } inline int QuMax(int l,int r){ int x=split(l,r); return a[x].maxn-a[x].minn; } inline int QuMin(int l,int r){ int x; if(r-l<=1){ x=split(l,r-1); return a[x].rb; }else{ x=split(l+1,r-1); return a[x].ms; } } }t; int main(){ n=read(),m=read(); s[0]=INF; for(int i=1;i<=n;i++){ s[i]=read(); } s[n+1]=INF; t.sz=n+2; t.rt=t.build(0,n+1,0); while(m--){ char opt=getc(); switch(opt){ case 'e':{ int wz=read(),v=read(); t.MoMerge(wz,v); break; } case 'n':{ int wz=read(),v=read(); t.MoInsert(wz,v); break; } case 'a':{ int l=read(),r=read(); write(t.QuMax(l,r)); putc('\n'); break; } case 'i':{ int l=read(),r=read(); write(t.QuMin(l,r)); putc('\n'); break; } } } flush(); } ``` 再见 qwq~