既然是中文题目,这里便不给题意。
分析:
这个题的做法据说是启发式合并?
但是我不会啊……
进入正题,LCT是怎样做掉这道题的。记得在前面的一篇《大融合》的题解中,介绍过LCT维护子树信息的做法。
一句话概括就是要维护虚子树和实子树的size,适时修改,保持其正确性。
这道题关键并不在这,但我们必须要维护这样一个信息才可以做。
很简单很直观的一个想法,因为我们每次合并两棵树时,新的重心必然出现在原来两个重心的路径上。
这是为什么?我们假设如果不在这条路径上,而是其中一棵树的其他子树的某一点,那么我们发现这一点比起之前,size较大的一棵子树上又缀了一棵树(以这个点为根),所以一定不优。
于是我们就合并树后把两棵原树的重心打通,(放到一个splay里),这时候尺寸就派上用场了,我们就在这个splay里查找,因为重心反正肯定存在于这个splay中了,那么我们就维护一个左尺寸,一个右尺寸。左边大了我们就让重心往左移动,右边大了就往右移动,直到两边的尺寸都小于等于总尺寸的一半,就好啦!(别忘了多个重心时的编号最小化)
代码:
1 #include<bits/stdc++.h> 2 #define lc(x) t[x][0] 3 #define rc(x) t[x][1] 4 using namespace std; 5 const int N=100005; 6 const int inf=0x3f3f3f3f; 7 struct LCT{ 8 int t[N][2],s[N],rev[N],fa[N],sx[N],sz[N],tp; 9 void pushup(int x){ 10 sz[x]=sz[lc(x)]+sz[rc(x)]+sx[x]+1; 11 } bool pdrt(int x){ 12 return rc(fa[x])!=x&&lc(fa[x])!=x; 13 } void revers(int x){ 14 rev[x]^=1;swap(lc(x),rc(x)); 15 } void pushdown(int x){ 16 if(rev[x]){ rev[x]=0; 17 if(lc(x)) revers(lc(x)); 18 if(rc(x)) revers(rc(x)); 19 } return ; 20 } void rotate(int x){ 21 int y=fa[x];int z=fa[y]; 22 int dy=(rc(y)==x),dz=(rc(z)==y); 23 if(!pdrt(y)) t[z][dz]=x; 24 t[y][dy]=t[x][dy^1];fa[t[y][dy]]=y; 25 t[x][dy^1]=y;fa[y]=x;fa[x]=z; 26 pushup(y);return ; 27 } void splay(int x){ 28 s[++tp]=x; 29 for(int i=x;!pdrt(i);i=fa[i]) 30 s[++tp]=fa[i]; 31 while(tp) pushdown(s[tp--]); 32 while(!pdrt(x)){ 33 int y=fa[x];int z=fa[y]; 34 if(!pdrt(y)) 35 if(rc(y)==x^rc(z)==y) rotate(x); 36 else rotate(y);rotate(x); 37 } pushup(x);return ; 38 } void access(int x){ 39 for(int i=0;x;x=fa[i=x]) 40 splay(x),sx[x]+=sz[rc(x)], 41 sx[x]-=sz[rc(x)=i],pushup(x); 42 } void mkrt(int x){ 43 access(x);splay(x);revers(x); 44 } void split(int x,int y){ 45 mkrt(x);access(y);splay(y); 46 } void link(int x,int y){ 47 split(x,y);sx[fa[x]=y]+=sz[x]; 48 pushup(y); 49 } int update(int x){ 50 int l,r,o=sz[x]&1,sm=sz[x]>>1, 51 ls=0,rs=0,np=inf,nl,nr; 52 while(x){ 53 pushdown(x); 54 nl=sz[l=lc(x)]+ls;nr=sz[r=rc(x)]+rs; 55 if(nl<=sm&&nr<=sm){ 56 if(o){np=x;break;} 57 else if(np>x) np=x; 58 } if(nl<nr) ls+=sz[l]+sx[x]+1,x=r; 59 else rs+=sz[r]+sx[x]+1,x=l; 60 } splay(np);return np; 61 } 62 }t;int n,m,fa[N]; 63 int get(int x){ 64 return fa[x]==x?x:fa[x]=get(fa[x]); 65 } int main(){ 66 char c[5];int rox=0;//尤为重要,必须赋0; 67 scanf("%d%d",&n,&m); 68 for(int i=1;i<=n;i++) 69 t.sz[i]=1,fa[i]=i,rox^=i; 70 while(m--){ 71 scanf("%s",c);int x,y,z; 72 if(c[0]=='A'){ 73 scanf("%d%d",&x,&y);t.link(x,y); 74 t.split(x=get(x),y=get(y)); 75 z=t.update(y);rox=(rox^x^y^z); 76 fa[x]=fa[y]=fa[z]=z; 77 } else if(c[0]=='Q'){ 78 scanf("%d",&x); 79 printf("%d ",get(x)); 80 } else printf("%d ",rox); 81 } return 0; 82 }