luogu P4219 [BJOI2014]大融合

 

题解:原来LCT也能维护子树信息,我太Naive了

用LCT维护当前子树节点个数

具体做法维护siz[x]=当前Splay子树和指向当前Splay子树的虚边所代表的节点个数

auxsiz[x]=指向x节点的虚边代表的节点个数

Link的时候x,y都要makeroot一下(针对我的写法)

然后就在LCT的基础上维护auxsiz即可

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100009;


int n,TT;

int fa[maxn]={0},ch[maxn][2]={0},siz[maxn]={0},auxsiz[maxn]={0},rev[maxn]={0};
inline bool isroot(int x){
	return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}
inline void pushup(int x){
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1+auxsiz[x];
}
inline int son(int x){
	if(ch[fa[x]][0]==x)return 0;
	else return 1;
}
inline void pushdown(int x){
	if(rev[x]){
		rev[x]^=1;
		rev[ch[x][0]]^=1;
		rev[ch[x][1]]^=1;
		swap(ch[x][0],ch[x][1]);
	}
}
void Downfa(int x){
	if(!isroot(x))Downfa(fa[x]);
	pushdown(x);
}

inline void Rotate(int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(!isroot(y))ch[z][c]=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}

void Splay(int x){
	Downfa(x);
	while(!isroot(x)){
		int y=fa[x];
		if(isroot(y)){
			Rotate(x);
		}else{
			if(son(x)==son(y)){
				Rotate(y);Rotate(x);
			}else{
				Rotate(x);Rotate(x);
			}
		}
	}
}

void Access(int x){
	for(int t=0;x;){
		Splay(x);
		auxsiz[x]+=siz[ch[x][1]];
		auxsiz[x]-=siz[t];
		ch[x][1]=t;
		pushup(x);
		t=x;x=fa[x];
	}
}
void Makeroot(int x){
	Access(x);Splay(x);rev[x]^=1;
}
void Link(int x,int y){
	Makeroot(x);Makeroot(y);fa[x]=y;
	auxsiz[y]+=siz[x];pushup(y);
}
void Cut(int x,int y){
	Makeroot(x);Access(y);Splay(y);
	fa[ch[y][0]]=0;ch[y][0]=0;
	pushup(y);
}

int main(){
	scanf("%d%d",&n,&TT);
	for(int i=1;i<=n;++i)siz[i]=1;
	while(TT--){
		char opty=getchar();
		int x,y;
		while(opty!='Q'&&opty!='A')opty=getchar();
		scanf("%d%d",&x,&y);
		if(opty=='A'){
			Link(x,y);
		}else{
			Cut(x,y);
			Splay(x);Splay(y);
			printf("%lld\n",1LL*siz[x]*siz[y]);
			Link(x,y);
		}
	}
	return 0;
}

  

posted @ 2018-03-06 20:22  ws_zzy  阅读(120)  评论(0编辑  收藏  举报