题面:https://www.luogu.com.cn/problem/P3721
题解
好题
本题关键在于一个性质:spaly是二叉查找树,一棵子树对应一段连续的值域
然后我们尝试一下手玩spaly,发现2、3操作的本质就是把最左边的点拆下来,把儿子接给父亲,然后自己去当根
1操作的本质就是找到x的前驱后继中深度较大的那个点,然后插入。
接着有一个绝妙(其实也是比较正常)的想法:用每个点的值来作为编号(因为每个点的值互不相同)
这样一棵子树就可以对应一段连续的编号
我们要求的问题是点x的深度
再手玩一下spaly,发现2、3操作会使自己的儿子深度不变,自己深度变成1,其他点的深度+1
1操作就只会改变当前插入节点的深度
于是可以差分一下用树状数组维护
这个时候就有一个小问题,有一些没有插入的点的深度会也会被树状数组修改到
于是我们可以在插入这个点的时候减去它之前的值,再加上它现在的值
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
#define N 100005
struct node{int op,x;}a[N];
int hh[N],len;
int ch[N][2],fa[N],rt;
set<int> s;
set<int>::iterator it1,it2;
int ta[N];
int getsum(int x){int ret=0;while(x){ret+=ta[x];x-=(x&-x);}return ret;}
void update(int x,int k){while(x<=100001){ta[x]+=k;x+=(x&-x);}}
void modify(int l,int r,int k){update(l,k);update(r+1,-k);}
int main()
{
int n,i,tmp,ts;
int x,u,v,depx,depu,depv;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i].op);
if(a[i].op==1){
scanf("%d",&a[i].x);
hh[++len]=a[i].x;
}
}
sort(hh+1,hh+len+1);
len=unique(hh+1,hh+len+1)-hh-1;
for(i=1;i<=n;i++){
if(a[i].op==1){
x=lower_bound(hh+1,hh+len+1,a[i].x)-hh;
if(!s.empty()){
it1=s.lower_bound(x);it2=s.end();
if(it1!=s.begin()){it2=it1;it2--;}
//next:u pre:v
if(it1!=s.end()&&it2!=s.end()){
u=*it1;depu=getsum(u);
v=*it2;depv=getsum(v);
if(depu>depv){ch[u][0]=x;fa[x]=u;tmp=depu+1;}
else{ch[v][1]=x;fa[x]=v;tmp=depv+1;}
}
else if(it1!=s.end()){
u=*it1;depu=getsum(u);
ch[u][0]=x;fa[x]=u;tmp=depu+1;
}
else if(it2!=s.end()){
v=*it2;depv=getsum(v);
ch[v][1]=x;fa[x]=v;tmp=depv+1;
}
}
else{rt=x;tmp=1;}
printf("%d\n",tmp);
ts=getsum(x);//remove the effect before
modify(x,x,tmp-ts);
s.insert(x);
}
else if(a[i].op==2||a[i].op==4){
x=(*s.begin());depx=getsum(x);
printf("%d\n",depx);
modify(x,x,1-depx);
if(u=fa[x]){
if(ch[u][0]=ch[x][1])
fa[ch[x][1]]=u;
fa[rt]=x;ch[x][1]=rt;rt=x;fa[x]=0;
modify(u,len,1);
}
if(a[i].op==4){
rt=ch[x][1];fa[rt]=0;
modify(1,len,-1);
s.erase(s.begin());
}
}
else if(a[i].op==3||a[i].op==5){
it1=s.end();it1--;
x=(*it1);depx=getsum(x);
printf("%d\n",depx);
modify(x,x,1-depx);
if(u=fa[x]){
if(ch[u][1]=ch[x][0])
fa[ch[x][0]]=u;
fa[rt]=x;ch[x][0]=rt;rt=x;fa[x]=0;
modify(1,u,1);
}
if(a[i].op==5){
rt=ch[x][0];fa[rt]=0;
modify(1,len,-1);
s.erase(it1);
}
}
}
}