【刷题】BZOJ 4530 [Bjoi2014]大融合

Description

小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。

这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够

联通的树上路过它的简单路径的数量。

例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因

为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。

现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的

询问。

Input

第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。

接下来的Q行,每行是如下两种格式之一:

A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。

Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。

1≤N,Q≤100000

Output

对每个查询操作,输出被查询的边的负载。

Sample Input

8 6  
A 2 3  
A 3 4  
A 3 8  
A 8 7  
A 6 5  
Q 3 8

Sample Output

6

Solution

LCT的特殊操作——维护子树信息

开个额外的Isize,记录节点虚子树的信息和

然后就裸的题目了

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
const int MAXN=100000+10;
int n,q;
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LCT{
	int ch[MAXN][2],fa[MAXN],rev[MAXN],size[MAXN],Isize[MAXN],stack[MAXN],cnt;
	inline bool nroot(int x)
	{
		return lc(fa[x])==x||rc(fa[x])==x;
	}
	inline void reverse(int x)
	{
		std::swap(lc(x),rc(x));
		rev[x]^=1;
	}
	inline void pushup(int x)
	{
		size[x]=size[lc(x)]+size[rc(x)]+Isize[x]+1;
	}
	inline void pushdown(int x)
	{
		if(rev[x])
		{
			if(lc(x))reverse(lc(x));
			if(rc(x))reverse(rc(x));
			rev[x]=0;
		}
	}
	inline void rotate(int x)
	{
		int f=fa[x],p=fa[f],c=(rc(f)==x);
		if(nroot(f))ch[p][rc(p)==f]=x;
		fa[ch[f][c]=ch[x][c^1]]=f;
		fa[ch[x][c^1]=f]=x;
		fa[x]=p;
		pushup(f);
		pushup(x);
	}
	inline void splay(int x)
	{
		cnt=0;
		stack[++cnt]=x;
		for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
		while(cnt)pushdown(stack[cnt--]);
		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x);
		pushup(x);
	}
	inline void access(int x)
	{
		for(register int y=0;x;x=fa[y=x])
		{
			splay(x);
			Isize[x]+=size[rc(x)];
			rc(x)=y;
			Isize[x]-=size[rc(x)];
			pushup(x);
		}
	}
	inline void makeroot(int x)
	{
		access(x);splay(x);reverse(x);
	}
	inline void split(int x,int y)
	{
		makeroot(x);access(y);splay(y);
	}
	inline void link(int x,int y)
	{
		makeroot(x);access(y);splay(y);
		fa[x]=y;
		Isize[y]+=size[x];
		pushup(y);
	}
};
LCT T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
	read(n);read(q);
	while(q--)
	{
		char opt[1];int x,y;
		scanf("%s",opt);read(x);read(y);
		if(opt[0]=='A')T.link(x,y);
		if(opt[0]=='Q')
		{
			T.split(x,y);
			write(1ll*(T.size[y]-T.size[x])*T.size[x],'\n');
		}
	}
	return 0;
}
posted @ 2018-04-05 12:14  HYJ_cnyali  阅读(124)  评论(0编辑  收藏  举报