loj2230 「BJOI2014」大融合

LCT裸题

我LCT学傻了这题明显可以树剖我不会树剖了

本来的siz是Splay上的子树和,并没有什么用。

所以每个点维护虚子树和子树和

虚子树和即虚边连接的子树和,且只有在access和link操作更改。

注意link操作

原来的link:

void link(int a,int b){makeroot(a);father[a]=b;}

现在的link:

//siz[i] i的子树和
//_siz[i] i的虚子树和
void link(int a,int b){makeroot(a);father[a]=b;_siz[b]+=siz[a];update(b);}

然而上面是错的,因为a会成为b和b所有爸爸的虚子树和,你只更新了b。你错了。(滑稽)

所以要先把b也放到根。

void link(int a,int b){makeroot(a);makeroot(b);father[a]=b;_siz[b]+=siz[a];update(b);}
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
using namespace std;
#define rg register
#define il inline
#define sta static
#define vd void
il int gi(){
	sta int x,flg;sta char ch;
	x=flg=0,ch=getchar();
	while(!isdigit(ch)){if(ch=='-')flg=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return flg?-x:x;
}
const int maxn=100001;
int ch[maxn][2],fa[maxn],siz[maxn],_siz[maxn];
bool rev[maxn];
typedef const int& fast;
il bool isrt(fast x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
il vd upd(fast x){if(x)siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1+_siz[x];}
il vd Rev(fast x){if(x)rev[x]^=1,std::swap(ch[x][0],ch[x][1]);}
il vd down(fast x){
	if(!isrt(x))down(fa[x]);
	if(rev[x])Rev(ch[x][0]),Rev(ch[x][1]),rev[x]=0;
}
il vd rotate(fast x){
	sta int y,z,o;y=fa[x],z=fa[y],o=ch[y][1]==x;
	if(!isrt(y))ch[z][ch[z][1]==y]=x;fa[x]=z;
	ch[y][o]=ch[x][!o];fa[ch[x][!o]]=y;
	fa[y]=x,ch[x][!o]=y;
	upd(y);
}
il vd splay(fast x){
	down(x);
	sta int y,z;
	for(y=fa[x],z=fa[y];!isrt(x);rotate(x),y=fa[x],z=fa[y])
		if(!isrt(y))rotate(((ch[y][0]==x)^(ch[z][0]==y))?x:y);
	upd(x);
}
il vd access(int x){for(rg int y=0;x;x=fa[y=x])splay(x),_siz[x]+=siz[ch[x][1]]-siz[y],ch[x][1]=y,upd(x);}
il vd makert(fast x){access(x),splay(x),Rev(x);}
il vd link(fast x,fast y){makert(x),makert(y),fa[x]=y,_siz[y]+=siz[x],upd(y);}
il vd split(fast x,fast y){makert(x),access(y),splay(y);}
int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	int n=gi(),q=gi(),x,y;char opt[3];
	for(rg int i=1;i<=n;++i)siz[i]=1;
	while(q--){
		scanf("%s",opt);x=gi(),y=gi();
		if(opt[0]=='A')link(x,y);
		else split(x,y),printf("%lld\n",1ll*siz[x]*(siz[y]-siz[x]));
	}
	return 0;
}
posted @ 2018-01-05 14:15  菜狗xzz  阅读(256)  评论(0编辑  收藏  举报