小强要在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 )。
现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问。
对于 40 %的数据, N , Q ≤ 103
对于 100 %的数据, 1 ≤ N , Q ≤ 105
首先先按照题目给出的所有边建出一棵树并求出 dfs 序。
对于询问操作,可以发现答案为儿子节点所在子树 Size *(父亲联通块大小-儿子节点所在子树 Size )。
不难发现某节点所在子树的所有节点 dfs 序是一段连续的区间,又因为某节点所在子树 Size 会因为修改操作的发生改变,因此我们可以采用线段树。
一开始对于每个点都种一颗线段树,修改操作其实就是将两棵线段树合并,同时维护每个点在所在联通块的祖先(即线段树的根),就能轻易地完成询问操作。
时间复杂度为 O ( n log n )。
var
dfx,dep,las:array[0..100100] of longint;
xw:array[0..100000,1..3] of longint;
n,q,i,j,k,l,o,p,a,b,w,tt,zz,d1,d2,qq:longint;
root,fa,f:array[0..100100] of longint;
tr:array[0..4800100,1..3] of longint;
lb,be,la,ne:array[0..200100] of longint; ch:char;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function gf(o:longint):longint;
begin
if f[o]=o then exit(o);
f[o]:=gf(f[o]); exit(f[o]);
end;
procedure dg(o,u:longint);
var
i:longint;
begin
inc(qq); dfx[o]:=qq; dep[o]:=u; las[o]:=qq; i:=be[o];
while i<>0 do
begin
if fa[o]<>lb[i] then
begin
fa[lb[i]]:=o; dg(lb[i],u+1);
las[o]:=max(las[o],las[lb[i]]);
end;
i:=ne[i];
end;
end;
procedure fk(p,l,r,mb:longint);
var mid:longint;
begin
tr[p,3]:=1;
if l=r then exit;
inc(o); mid:=(l+r) div 2;
if mb<=mid then
begin tr[p,1]:=o; fk(o,l,mid,mb) end
else begin tr[p,2]:=o; fk(o,mid+1,r,mb); end;
end;
function ques(o,l,r,ll,rr:longint):longint;
var ls,rs,mid:longint;
begin
if o=0 then exit(0);
if (l=ll) and (r=rr) then exit(tr[o,3]);
mid:=(l+r) div 2; ls:=tr[o,1]; rs:=tr[o,2];
if rr<=mid then ques:=ques(ls,l,mid,ll,rr)
else if ll>mid then ques:=ques(rs,mid+1,r,ll,rr)
else ques:=ques(ls,l,mid,ll,mid)+ques(rs,mid+1,r,mid+1,rr);
end;
function hb(x,y:longint):longint;
begin
if x=0 then exit(y);
if y=0 then exit(x);
tr[x,3]:=tr[x,3]+tr[y,3];
tr[x][1]:=hb(tr[x][1],tr[y][1]);
tr[x][2]:=hb(tr[x][2],tr[y][2]);
exit(x);
end;
begin
readln(n,q);
for i:=1 to q do
begin
read(ch); readln(a,b);
if ch='A' then
begin
inc(o); ne[la[a]]:=o; la[a]:=o;
lb[o]:=b; if be[a]=0 then be[a]:=o;
inc(o); ne[la[b]]:=o; la[b]:=o;
lb[o]:=a; if be[b]=0 then be[b]:=o; xw[i,3]:=2;
end else xw[i,3]:=1; xw[i,1]:=a; xw[i,2]:=b;
end; o:=0;
for i:=1 to n do
if fa[i]=0 then
begin
fa[i]:=-1; dg(i,1);
end;
for i:=1 to n do
begin
f[i]:=i; inc(o); root[i]:=o;
fk(root[i],1,n,dfx[i]);
end;
for i:=1 to q do
if xw[i,3]=1 then
begin
a:=xw[i,1]; b:=xw[i,2];
if dep[a]>dep[b] then
begin tt:=a; a:=b; b:=tt; end;
zz:=gf(a); d1:=ques(root[zz],1,n,dfx[zz],las[zz]);
d2:=ques(root[zz],1,n,dfx[b],las[b]);
writeln(d2*(d1-d2));
end
else
begin
a:=xw[i,1]; b:=xw[i,2];
if dep[a]>dep[b] then
begin tt:=a; a:=b; b:=tt; end;
zz:=gf(a); f[gf(b)]:=zz;
root[zz]:=hb(root[zz],root[b]);
end;
end.