1 条题解
-
0
#include<cstdio> #include<cstdlib> #define R register int #define I inline void const int N=100009,INF=2147483647; int f[N],c[N][2],si[N],s[N],h[N]; bool r[N]; #define lc c[x][0] #define rc c[x][1] inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;} I pushup(R x){ s[x]=s[lc]+s[rc]+si[x]+1; } I pushdown(R x){ if(r[x]){ R t=lc;lc=rc;rc=t; r[lc]^=1;r[rc]^=1;r[x]=0; } } I pushall(R x){ if(nroot(x))pushall(f[x]); pushdown(x); } I rotate(R x){ R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k]; if(nroot(y))c[z][c[z][1]==y]=x; f[f[f[c[c[x][!k]=y][k]=w]=y]=x]=z;pushup(y);//为三行rotate打call } I splay(R x){ pushall(x); R y; while(nroot(x)){ if(nroot(y=f[x]))rotate((c[f[y]][0]==y)^(c[y][0]==x)?x:y); rotate(x); } pushup(x); } I access(R x){ for(R y=0;x;x=f[y=x]){ splay(x); si[x]+=s[rc]; si[x]-=s[rc=y]; pushup(x); } } I makeroot(R x){ access(x);splay(x); r[x]^=1; } I split(R x,R y){ makeroot(x); access(y);splay(y); } I link(R x,R y){ split(x,y); si[f[x]=y]+=s[x]; pushup(y); } int geth(R x){ if(h[x]==x)return x; return h[x]=geth(h[x]); } inline int update(R x){ R l,r,ji=s[x]&1,sum=s[x]>>1,lsum=0,rsum=0,newp=INF,nowl,nowr; while(x){ pushdown(x);//注意pushdown nowl=s[l=lc]+lsum;nowr=s[r=rc]+rsum; if(nowl<=sum&&nowr<=sum){ if(ji){newp=x;break;}//剪枝,确定已经直接找到 else if(newp>x)newp=x;//选编号最小的 } if(nowl<nowr)lsum+=s[l]+si[x]+1,x=r; else rsum+=s[r]+si[x]+1,x=l;//缩小搜索区间 } splay(newp);//保证复杂度 return newp; } #define G ch=getchar() #define gc G;while(ch<'-')G #define in(z) gc;z=ch&15;G;while(ch>'-')z*=10,z+=ch&15,G; int main(){ register char ch; R n,m,x,y,z,Xor=0; in(n);in(m); for(R i=1;i<=n;++i)s[i]=1,h[i]=i,Xor^=i; while(m--){ gc; switch(ch){ case 'A':in(x);in(y);link(x,y); split(x=geth(x),y=geth(y));//提出原重心路径 z=update(y); Xor=Xor^x^y^z; h[x]=h[y]=h[z]=z;//并查集维护好 break; case 'Q':in(x);printf("%d\n",geth(x));break; case 'X':gc;gc;printf("%d\n",Xor); } } return 0; }
- 1
信息
- ID
- 5175
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者