题面: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);
			}
		}
	}
}