原题链接
我的方法是用另外一颗splay(以原来输入的关键码作为关键字)维护原树节点深度信息,使得在操作时能在原树上快速定位与查询。
为了方便,以下提到的splay都是维护信息的那颗splay,而不是用来模拟原来操作的那棵树。
对于插入,直接在splay中insert,再看它的前驱与后继谁的左/右儿子是空的,记录dep=dep[..]+1
对于单旋最小值m,发现在原树中m的右子树的深度不变,m深度变为1,其他点深度+1。记m在原树中的父亲为f,可以在splay中把f的前驱旋转到根,再把根的右子树打上+1的标记。单旋最小值m后删除m的话,发现在原树中m的右子树的深度-1,其他点深度不变,就对应的在splay中把f旋转到根,f的左子树打上-1,然后删除m即可。
最大值同理。
复杂度O(nlogn)
#include#include #include #include #include #include #define R return 0 using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int N=150050; void read(int &re) { char ch=getchar();int g=1; while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();} re=0; while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48,ch=getchar(); re*=g; } struct node { int fa,ch[2]; }tr[N]; int dep[N],ch[N][2],fa[N],siz[N],dfn[N],sz=0,root=0,cnt=0,key[N]; int add[N],rt=0; inline bool ge(int x) {return ch[fa[x]][1]==x;} void up(int x) { siz[x]=1; if(ch[x][0]) siz[x]+=siz[ch[x][0]]; if(ch[x][1]) siz[x]+=siz[ch[x][1]]; } void pushdown(int x) { if(x&&add[x]) { dep[x]+=add[x]; if(ch[x][0]) add[ch[x][0]]+=add[x]; if(ch[x][1]) add[ch[x][1]]+=add[x]; add[x]=0; } } void rotate(int x) { pushdown(fa[x]);pushdown(x); int f=fa[x],g=fa[f],wh=ge(x); ch[f][wh]=ch[x][wh^1]; fa[ch[f][wh]]=f; ch[x][wh^1]=f; fa[f]=x; fa[x]=g; if(g) ch[g][ch[g][1]==f]=x; up(f),up(x); } void splay(int x,int goal) { if(!x) return ; for(int f;(f=fa[x])!=goal;rotate(x)) if(fa[f]!=goal) rotate(ge(x)==ge(f)?f:x); if(!goal) root=x; } void clear(int x) { ch[x][0]=ch[x][1]=fa[x]=dep[x]=siz[x]=dfn[x]=add[x]=key[x]=0; tr[x].ch[0]=tr[x].ch[1]=tr[x].fa=0; } int pre() { int now=root;pushdown(now); if(!ch[now][0]) return 0; now=ch[now][0]; pushdown(now); while(ch[now][1]) now=ch[now][1],pushdown(now); return now; } int nex() { int now=root;pushdown(now); if(!ch[now][1]) return 0; now=ch[now][1]; pushdown(now); while(ch[now][0]) now=ch[now][0],pushdown(now); return now; } int insert(int k) { if(!root) { sz++;root=sz;dep[sz]=1;siz[sz]=1;dfn[sz]=++cnt;key[sz]=k; rt=sz;dep[sz]=1; return sz; } int now=root,f=0; while(1) { pushdown(now); int wh=key[now]<k; f=now; now=ch[now][wh]; if(!now) { now=++sz; ch[f][wh]=now;fa[now]=f;key[now]=k;siz[now]=1; dfn[now]=++cnt;up(f);splay(now,0); return now; } } } int findmin() { int now=root;pushdown(now); while(ch[now][0]) now=ch[now][0],pushdown(now); return now; } int findmax() { int now=root;pushdown(now); while(ch[now][1]) now=ch[now][1],pushdown(now); return now; } //debug void allpushdown(int x) { pushdown(x); if(ch[x][0]) allpushdown(ch[x][0]); if(ch[x][1]) allpushdown(ch[x][1]); } int main() { int i,j,x,y,T,k; read(T); for(i=1;i<=T;++i) { read(y); clear(0); if(y==1) { read(x); k=insert(x); if(siz[k]==1) { printf("1\n"); continue; } int p=pre(),n=nex(); if(!p||!n) { p=p+n; if(key[p] 1]=k; else tr[p].ch[0]=k; tr[k].fa=p; dep[k]=dep[p]+1; printf("%d\n",dep[k]); continue; } clear(0); if(tr[p].ch[1]) tr[n].ch[0]=k,tr[k].fa=n,dep[k]=dep[n]+1; else if(tr[n].ch[0]) tr[p].ch[1]=k,tr[k].fa=p,dep[k]=dep[p]+1; printf("%d\n",dep[k]); //insert min! } else if(y==2) { x=findmin(); pushdown(x); printf("%d\n",dep[x]); dep[x]=1; if(x==rt) continue; int f=tr[x].fa,now=x; tr[x].fa=0;tr[tr[x].ch[1]].fa=f; tr[f].ch[0]=tr[x].ch[1];tr[x].ch[1]=rt; tr[rt].fa=x;rt=x; clear(0); splay(f,0); now=pre(); splay(now,0); if(ch[now][1]) add[ch[now][1]]++; } else if(y==3) { x=findmax(); pushdown(x); printf("%d\n",dep[x]); dep[x]=1; if(x==rt) continue; int f=tr[x].fa,now=x; tr[x].fa=0;tr[tr[x].ch[0]].fa=f; tr[f].ch[1]=tr[x].ch[0];tr[x].ch[0]=rt; tr[rt].fa=x;rt=x; clear(0); splay(f,0); now=nex(); splay(now,0); if(ch[now][0]) add[ch[now][0]]++; } else if(y==4) {//!!!!!!!!!!!!!!! x=findmin(); pushdown(x); printf("%d\n",dep[x]); int f=tr[x].fa; if(x==rt) rt=tr[x].ch[1]; tr[tr[x].ch[1]].fa=f;tr[f].ch[0]=tr[x].ch[1]; tr[x].ch[1]=tr[x].ch[0]=tr[x].fa=0; clear(0); splay(x,0); root=ch[x][1];fa[root]=0;clear(x); if(f) { splay(f,0); if(ch[f][0]) add[ch[f][0]]--; } else { if(root) add[root]--; else clear(rt),rt=0; } } else if(y==5) { x=findmax(); pushdown(x); printf("%d\n",dep[x]); int f=tr[x].fa; if(x==rt) rt=tr[x].ch[0]; tr[tr[x].ch[0]].fa=f;tr[f].ch[1]=tr[x].ch[0]; tr[x].ch[1]=tr[x].ch[0]=tr[x].fa=0; clear(0); splay(x,0); root=ch[x][0];fa[root]=0;clear(x); if(f) { splay(f,0); if(ch[f][1]) add[ch[f][1]]--; } else { if(root) add[root]--; else clear(rt),rt=0; } } } return 0; }