Description
小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。
对于40%的数据,N,Q≤1000
对于100%的数据,1≤N,Q≤100000
Solution
所求答案就是给定边两端子树size的乘积,由于我不cai会de在kou线jiao做写了一发lct维护子树size
考虑用lct维护加边的操作
用siz[x]记录点x所有虚边连向的儿子所在子树的大小(绕
用size[x]记录点x在splay上左儿子size+右儿子size+虚儿子+1
容易发现当我们access(x)的时候它的子树大小就是siz[x]+1,当我们mroot(x)的时候它的子树大小则是size[x]
写的时候注意一下access操作和link操作的变化就行了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=200005;
struct treeNode {
int fa,son[2],size,siz,rev,is_root;
} t[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int x) {
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+t[x].siz+1;
}
void push_down(int x) {
if (!t[x].rev) return;
t[x].rev=0; std:: swap(t[x].son[0],t[x].son[1]);
if (t[x].son[0]) t[t[x].son[0]].rev^=1;
if (t[x].son[1]) t[t[x].son[1]].rev^=1;
}
void rotate(int x) {
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[y].son[k]=t[x].son[!k]; if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
t[y].fa=x; t[x].son[!k]=y;
t[x].fa=z;
if (t[y].is_root) {
t[y].is_root=0;
t[x].is_root=1;
} else t[z].son[t[z].son[1]==y]=x;
push_up(y); push_up(x);
}
void remove(int x) {
if (!t[x].is_root) remove(t[x].fa);
push_down(x);
}
void splay(int x) {
remove(x);
while (!t[x].is_root) {
int y=t[x].fa; int z=t[y].fa;
if (!t[y].is_root) {
if ((t[z].son[1]==y)^(t[y].son[1]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {
int y=0;
while (x) {
splay(x);
t[y].is_root=0;
t[t[x].son[1]].is_root=1;
t[x].siz+=t[t[x].son[1]].size;
t[x].son[1]=y;
t[x].siz-=t[y].size;
push_up(x);
y=x; x=t[x].fa;
}
}
void mroot(int x) {
access(x); splay(x); t[x].rev^=1;
}
void link(int x,int y) {
mroot(x); mroot(y); t[x].fa=y; t[y].siz+=t[x].size; push_up(y);
}
int main(void) {
int n=read(),q=read();
rep(i,1,n) t[i].size=t[i].is_root=1;
for (;q--;) {
char opt=getchar();
for (;opt!='A'&&opt!='Q';opt=getchar());
int x=read(),y=read();
if (opt=='A') {
link(x,y);
} else {
mroot(x); access(y); splay(x);
printf("%lld\n", 1LL*(t[y].siz+1)*(t[x].size-t[y].siz-1));
}
}
return 0;
}