码迷,mamicode.com
首页 > 其他好文 > 详细

[HNOI2017]单旋

时间:2017-12-21 19:39:23      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:log   algorithm   长度   main   math   ras   node   span   mat   

题解:

我们可以单独的用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 }

 

[HNOI2017]单旋

标签:log   algorithm   长度   main   math   ras   node   span   mat   

原文地址:http://www.cnblogs.com/Landlord-greatly/p/8081752.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!