[HNOI2017]单旋
题解:
我们可以单独的用LCT来维护每个点的深度(先把当前根转到根,再查询到根的路径长度就可以了),这棵splay由于只需要旋转最大最小值,手玩发现树的形态基本没变,所以我们就可以手动维护这个splay的形态,记录好根,父亲,儿子的状态然后用LCT求深度即可.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstring> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #define RG register 11 #define LL long long int 12 #define MAXN 500010 13 using namespace std; 14 const int INF=1e9; 15 struct node{ 16 int id;int x; 17 }op[MAXN]; 18 int m; 19 int root; 20 int ch[MAXN][2],fa[MAXN],siz[MAXN],rev[MAXN]; 21 int st[MAXN],top; 22 int pp[MAXN]; 23 int c[MAXN][2],f[MAXN]; 24 set<int> s; 25 set<int>::iterator it; 26 void clear(int x){ch[x][0]=ch[x][1]=fa[x]=0;} 27 void up(int x){siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;} 28 bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} 29 void down(int x) 30 { 31 if(rev[x]){ 32 swap(ch[x][0],ch[x][1]); 33 rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]^=1; 34 } 35 } 36 void rotate(int x) 37 { 38 int old=fa[x],oldf=fa[old],rel=(ch[old][1]==x); 39 if(!isroot(old)) ch[oldf][ch[oldf][1]==old]=x; 40 fa[x]=oldf;fa[ch[x][rel^1]]=old;ch[old][rel]=ch[x][rel^1]; 41 fa[old]=x;ch[x][rel^1]=old; 42 up(old);up(x);return; 43 } 44 void splay(int x) 45 { 46 int old,oldf,now=x;top=0;st[++top]=now; 47 while(!isroot(now)) st[++top]=fa[now],now=fa[now]; 48 while(top>0){down(st[top]);top--;} 49 while(!isroot(x)) 50 { 51 old=fa[x];oldf=fa[old]; 52 if(!isroot(old)) 53 { 54 if((ch[old][0]==x)^(ch[oldf][0]==old)) rotate(x); 55 else rotate(old); 56 } 57 rotate(x); 58 } 59 } 60 void access(int x){int t(0);while(x) splay(x),ch[x][1]=t,t=x,up(x),x=fa[x];} 61 void makeroot(int x){access(x);splay(x);rev[x]^=1;} 62 void link(int x,int y){ if(!x||!y) return; makeroot(x);fa[x]=y,up(y);} 63 void cut(int x,int y){ 64 if(!x||!y) return; 65 makeroot(x);access(y);splay(y); 66 ch[y][0]=fa[x]=0,up(x),up(y); 67 } 68 int query(int x){makeroot(root);access(x);splay(x);return siz[x];} 69 int main() 70 { 71 freopen("1.in","r",stdin); 72 scanf("%d",&m); 73 for(int i=1;i<=m;i++){ 74 scanf("%d",&op[i].id); 75 if(op[i].id==1) scanf("%d",&op[i].x),pp[++pp[0]]=op[i].x; 76 } 77 sort(pp+1,pp+pp[0]+1);int cnt=unique(pp+1,pp+pp[0]+1)-pp-1; 78 s.insert(INF);s.insert(-INF);int tot=0; 79 for(int i=1;i<=m;i++) 80 { 81 if(op[i].id==1){ 82 tot++;op[i].x=lower_bound(pp+1,pp+cnt+1,op[i].x)-pp; 83 if(tot==1) {root=op[i].x;printf("1\n");} 84 else{ 85 it=s.upper_bound(op[i].x);int nex=*it;it--;int pre=*it; 86 int dep=0,x; 87 if(pre!=-INF){int now=query(pre);if(now>dep){dep=now,x=pre;}} 88 if(nex!=INF){int now=query(nex);if(now>dep){dep=now,x=nex;}} 89 printf("%d\n",dep+1); 90 c[x][op[i].x>x]=op[i].x;f[op[i].x]=x;link(x,op[i].x); 91 } 92 s.insert(op[i].x); 93 } 94 if(op[i].id==2){ 95 if(tot==1) printf("1\n"); 96 else{ 97 it=s.begin();it++;int x=*it;int y=c[x][1],z=f[x],dep=query(x); 98 if(root!=x){ 99 cut(x,z);cut(x,y);link(z,y);link(x,root); 100 c[x][1]=root;f[root]=x;f[x]=0;root=x; 101 f[y]=z;c[z][0]=y; 102 } 103 printf("%d\n",dep); 104 } 105 } 106 if(op[i].id==3){ 107 if(tot==1){printf("1\n");continue;} 108 else{ 109 it=s.end();it--;it--;int x=*it;int y=c[x][0],z=f[x],dep=query(x); 110 if(root!=x){ 111 cut(x,z);cut(x,y);link(z,y);link(root,x); 112 c[x][0]=root;f[root]=x;f[x]=0;root=x; 113 f[y]=z;c[z][1]=y; 114 } 115 printf("%d\n",dep); 116 } 117 } 118 if(op[i].id==4){ 119 if(tot==1){s.erase(s.find(root));clear(root);root=0;tot--;printf("1\n");} 120 else{ 121 it=s.begin();it++;int x=*it;int y=c[x][1],z=f[x],dep=query(x);tot--; 122 if(x==root) root=y; 123 cut(x,y);cut(x,z);link(y,z);clear(x); 124 f[y]=z;c[z][0]=y; 125 printf("%d\n",dep);s.erase(s.find(x)); 126 } 127 } 128 if(op[i].id==5){ 129 if(tot==1){s.erase(s.find(root));clear(root);root=0;tot--;printf("1\n");} 130 else{ 131 it=s.end();it--;it--;int x=*it;int y=c[x][0],z=f[x],dep=query(x);tot--; 132 if(x==root) root=y; 133 cut(x,y);cut(x,z);link(y,z);clear(x); 134 f[y]=z;c[z][1]=y; 135 printf("%d\n",dep);s.erase(s.find(x)); 136 } 137 } 138 } 139 return 0; 140 }