bzoj3510 首都
题目描述:给你n个点和m个操作:
1.链接两个点。
2.查询某点所在树的重心。
3.查询所有树重心的异或和。
其实就是lct维护虚子树,链接时新重心一定在原来的两重心连线上,相当于splay查询区间第k大值(区间中点)。
代码:
#include<cstdio> #include<algorithm> #define N 100050 int n,m; int fa[N],rt[N],ch[N][2],s[N],sx[N],sr; bool res[N]; bool is_not_root(int x) { return (ch[fa[x]][0]==x)|(ch[fa[x]][1]==x); } void update(int x) { s[x]=s[ch[x][0]]+s[ch[x][1]]+sx[x]+1; } void reser(int x) { res[x]^=1; std::swap(ch[x][0],ch[x][1]); } void pushdown(int x) { if(res[x]) { res[x]=0; reser(ch[x][0]); reser(ch[x][1]); } } void down(int x) { if(is_not_root(x))down(fa[x]); pushdown(x); } void rotate(int x) { int y = fa[x],k = (ch[y][1]==x); if(is_not_root(y))ch[fa[y]][ch[fa[y]][1]==y]=x; fa[x]=fa[y]; ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y; ch[x][!k]=y,fa[y]=x; update(y),update(x); } void splay(int x) { down(x); while(is_not_root(x)) { int y = fa[x],z=fa[y]; if(is_not_root(y)) ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y); rotate(x); } } void access(int x) { int y = 0; while(x) { splay(x); sx[x]+=s[ch[x][1]]; sx[x]-=s[y]; ch[x][1]=y; update(x); y=x,x=fa[x]; } } void mtr(int x) { access(x); splay(x); reser(x); } void split(int x,int y) { mtr(x); access(y); splay(y); } void link(int x,int y) { split(x,y); fa[x]=y; sx[y]+=s[x]; update(y); } int findrt(int x) { if(rt[x]==x)return x; return rt[x]=findrt(rt[x]); } int getfa(int x) { int goal = s[x]>>1,tip = (s[x]&1); int ls = 0,rs = 0,ret = 0x7fffffff,vl,vr; while(x) { pushdown(x); vl = s[ch[x][0]]+ls; vr = s[ch[x][1]]+rs; if(vl<=goal&&vr<=goal) { if(tip){ret=x;break;} else if(ret>x)ret=x; } if(vl>vr) { rs += s[ch[x][1]]+sx[x]+1; x = ch[x][0]; }else { ls += s[ch[x][0]]+sx[x]+1; x = ch[x][1]; } } splay(ret); return ret; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { s[i]=1; sr^=i; rt[i]=i; } int u,v; char sc[10]; for(int i=1;i<=m;i++) { scanf("%s",sc); if(sc[0]=='X') { printf("%d\n",sr); }else if(sc[0]=='Q') { scanf("%d",&u); printf("%d\n",findrt(u)); }else { scanf("%d%d",&u,&v); link(u,v); u=findrt(u),v=findrt(v); split(u,v);//v=rt int r = getfa(v); sr = sr^u^v^r; rt[u] = rt[v] = rt[r] = r; } } return 0; }