记录编号 412464 评测结果 AAAAAAAAAA
题目名称 动态树 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 1.472 s
提交时间 2017-06-09 14:24:33 内存使用 6.78 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int n,m,fa[N],son[N][2],v[N],pre[N],suf[N];
bool root[N];
int apre[N],asuf[N];bool rev[N];
//v[x]表示子树x大小减去pre_child子树的大小 
//pre,suf表示一颗splay上v的前缀后缀和 
#define lc son[x][0]
#define rc son[x][1]
void flip(int x){
	swap(lc,rc);
	swap(pre[x],suf[x]);
	swap(apre[x],asuf[x]);
	rev[x]^=1;
}
void add_pre(int x,int d){
	pre[x]+=d;
	apre[x]+=d;
}
void add_suf(int x,int d){
	suf[x]+=d;
	asuf[x]+=d;
}
void pushdown(int x){
	if (!x) return;
	if (rev[x]){
		if (lc) flip(lc);
		if (rc) flip(rc);
		rev[x]=0;
	}
	if (apre[x]){
		if (lc) add_pre(lc,apre[x]);
		if (rc) add_pre(rc,apre[x]);
		apre[x]=0;
	}
	if (asuf[x]){
		if (lc) add_suf(lc,asuf[x]);
		if (rc) add_suf(rc,asuf[x]);
		asuf[x]=0;
	}
}
void rot(int x){
	int y=fa[x],z=fa[y];
	bool b=(x==son[y][1]);
	fa[son[y][b]=son[x][!b]]=y;
	fa[son[x][!b]=y]=x;
	fa[x]=z;
	if (son[z][0]==y) son[z][0]=x;else
	if (son[z][1]==y) son[z][1]=x;
	root[x]=root[y];root[y]=0;
}
void splay(int x){
	pushdown(x);
	for (;!root[x];rot(x)){
		int y=fa[x],z=fa[y];
		pushdown(z);pushdown(y);pushdown(x);
		if (!root[y]) rot((x==son[y][0])==(y==son[z][0])?y:x);
	}
}
//suf[x]即子树x的大小 
int top(int x){
	for (;;x=lc){
		pushdown(x);
		if (!lc) break;
	}
	splay(x);
	return x;
}
void link_r(int x,int y){
	y=top(y);
	v[x]-=suf[y];
	pre[x]-=suf[y];
	add_pre(y,pre[x]);
	root[rc=y]=0;
}
void cut_r(int x){
	int y=rc;
	if (!y) return;
	root[rc]=1;rc=0;
	y=top(y);
	add_pre(y,-pre[x]);
	v[x]+=suf[y];
	pre[x]+=suf[y];
}
void access(int x){
	splay(x);
	cut_r(x);
	while (fa[x]){
		int y=fa[x];
		splay(y);
		cut_r(y);
		link_r(y,x);
		splay(x);
	}
}
void makeroot(int x){
	access(x);
	flip(x);
}
int main()
{
	freopen("dynamic_tree.in","r",stdin);
	freopen("dynamic_tree.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) pre[i]=suf[i]=v[i]=root[i]=1;
	while (m--){
		int tp,x,y;
		scanf("%d%d",&tp,&x);
		if (tp==1) makeroot(x);
		if (tp==2) splay(x),printf("%d\n",suf[x]);
		if (tp==3){
			scanf("%d",&y);
			makeroot(y);
			fa[y]=x;
			access(x);
			v[x]+=suf[y];
			pre[x]+=suf[y];
			add_suf(x,suf[y]);
		}
	}
	return 0;
}