P4299 首都

题目

P4299 首都

做法

这题是动态维护树的重心,连边后找到两棵树的重心拉一条链(性质:新重心在链上),然后暴力爬

要注意:

1.是找重心的过程中要先把旋转标记放下来,因为\(Splay(x)\),这个操作只把\(x\)到根节点的跟上旋有关标记放下来
而找重心过程中跟整个链有关

2.并查集的时候记得把\(z\)也改变一下,不然会死循环,卡了好久\(emmm\)

My complete code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef int LL;
const LL maxn=200000,inf=0x3f3f3f3f;
inline LL Read(){
	LL x(0),f(1);char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
LL n,m,Xor;
LL son[maxn][2],fa[maxn],sta[maxn],f[maxn],isum[maxn],sum[maxn],r[maxn];
inline void Update(LL x){
	sum[x]=sum[son[x][0]]+sum[son[x][1]]+isum[x]+1;
}
inline bool Notroot(LL x){
	return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
inline void Pushr(LL x){
	swap(son[x][0],son[x][1]),r[x]^=1;
}
inline void Pushdown(LL x){
	if(r[x]){
		if(son[x][0]) Pushr(son[x][0]);
		if(son[x][1]) Pushr(son[x][1]);
		r[x]=0;
	}
}
inline void Rotate(LL x){
	LL y(fa[x]),z(fa[y]),lz(son[y][1]==x);
	if(Notroot(y)) son[z][son[z][1]==y]=x;fa[x]=z;
	son[y][lz]=son[x][lz^1];
	if(son[y][lz]) fa[son[y][lz]]=y;
	son[x][lz^1]=y; fa[y]=x;
	Update(y),Update(x);
}
inline void Splay(LL x){
	LL y(x),top(0);sta[++top]=y;
	while(Notroot(y)) sta[++top]=y=fa[y];
	while(top) Pushdown(sta[top--]);
	while(Notroot(x)){
		y=fa[x];
		if(Notroot(y)){
			LL z(fa[y]);
			if(((son[y][1]==x)^(son[z][1]==y))==0) Rotate(y);
			else Rotate(x);
		}Rotate(x);
	}
}
inline void Access(LL x){
	for(LL y=0;x;y=x,x=fa[x]){
	    Splay(x),isum[x]+=sum[son[x][1]];
		son[x][1]=y;isum[x]-=sum[son[x][1]];
		Update(x);
	}
}
inline void Makeroot(LL x){
	Access(x),Splay(x),Pushr(x);
}
inline void Split(LL x,LL y){
	Makeroot(x),Access(y),Splay(y);
}
inline void Link(LL x,LL y){
    Makeroot(x),Access(y),Splay(y);
    fa[x]=y;
    isum[y]+=sum[x];
    Update(y);
}

LL Get_fa(LL x){
	return f[x]=(f[x]==x?x:Get_fa(f[x]));
}
inline LL Get_w(LL x){
	LL ji=sum[x]&1,M=sum[x]>>1,lsum(0),rsum(0),new_w(inf),nowl,nowr;
	while(x){
		Pushdown(x);
		nowl=sum[son[x][0]]+lsum,nowr=sum[son[x][1]]+rsum;
		if(nowl<=M&&nowr<=M){
			if(ji){
				new_w=x;
				break;
			}else
			    new_w=min(new_w,x);
		}
		if(nowl<nowr){
			lsum+=sum[son[x][0]]+isum[x]+1;
			x=son[x][1];
		}else{
			rsum+=sum[son[x][1]]+isum[x]+1;
			x=son[x][0];
		}
	}
	Splay(new_w);
	return new_w;
}
int main(){
	n=Read(),m=Read();
	for(LL i=1;i<=n;++i)
	    sum[i]=1,f[i]=i,Xor^=i;
	while(m--){
		char s[100];
		scanf(" %s",s);
		if(s[0]=='X') printf("%d\n",Xor);
		else if(s[0]=='Q'){
			LL x(Read());
			printf("%d\n",Get_fa(x));
		}else{
			LL x(Read()),y(Read());
			Link(x,y);
			Split(x=Get_fa(x),y=Get_fa(y));
			LL z=Get_w(y);
			f[x]=f[y]=f[z]=z;
			Xor^=x^y^z;
		}
	}return 0;
}
posted @ 2019-01-28 17:57  y2823774827y  阅读(218)  评论(0编辑  收藏  举报