考虑到一次答案就是两点的子树和乘积。
我们先维护一个整个大树。
用并查集做小树的情况,树剖做子树大小的维护。
#include<iostream>
#include<cstdio>
#define ll long long
#define N 100005
ll n,q;
struct P{
ll opt,x,y;
}p[N];
ll cnt,head[N];
struct s{
int to,next;
}e[N << 1];
inline void add(int x,int y){
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
bool in[N];
ll fa[N];
inline void del(int x,int f){
in[x] = 1;
fa[x] = f;
for(int i = head[x];i;i = e[i].next){
int v = e[i].to;
if(v == f)continue;
del(v,x);
}
}
ll dfncnt;
ll siz[N],son[N],dfn[N],dep[N],top[N];
inline void dfs(int u,int f){
fa[u] = f;
siz[u] = 1;
fa[u] = f;
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(v == f)continue;
dfs(v,u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
inline void dfs2(int u,int t){
top[u] = t;
dfn[u] = ++dfncnt;
if(son[u])dfs2(son[u],t);
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(v == son[u] || v == fa[u])
continue;
dfs2(v,v);
}
}
//tree____cut
ll fi[N];
inline ll find(int u){
return (fi[u] == u) ? u : fi[u] = find(fi[u]);
}
inline void merge(int x,int y){
int fx = find(x),fy = find(y);
fi[fy] = fx;
}
//DSU
ll t[N << 1];
#define lowbit(x) (x & -x)
inline void change(int x,int y){
for(int i = x;i <= n;i += lowbit(i))
t[i] += y;
}
inline ll cha(int x){
ll ans = 0;
for(int i = x;i;i -= lowbit(i))
ans += t[i];
return ans;
}
//BIT
int main(){
scanf("%lld%lld",&n,&q);
for(int i = 1;i <= q;++i){
char a ;
while(a != 'A' && a != 'Q')
a = getchar();
if(a == 'A')
p[i].opt = 1,scanf("%lld%lld",&p[i].x,&p[i].y),add(p[i].x,p[i].y),add(p[i].y,p[i].x);
else
p[i].opt = 2,scanf("%lld%lld",&p[i].x,&p[i].y);
a = '.';
}
ll root = n + 1;
for(int i = 1;i <= n;++i){
if(!in[i]){
add(root,i);
add(i,root);
del(i,root);
}
}
dfs(root,0);
dfs2(root,root);
for(int i = 1;i <= n + 1;++i)
fi[i] = i;
n += 1;
change(1,1);
for(int i = 1;i <= q;++i){
ll x = p[i].x,y = p[i].y;
if(fa[x] == y)
std::swap(x,y);
if(p[i].opt == 1){
ll fx = find(x);
// std::cout<<x<<" "<<fx<<":"<<std::endl;
merge(x,y);
ll tag = cha(dfn[y]);
while(top[x] != top[fx]){
change(dfn[top[x]],tag);
// std::cout<<dfn[x]<<" "<<tag<<std::endl;
change(dfn[x] + 1,-tag);
// std::cout<<dfn[top[x]] + 1<<" "<<-tag<<std::endl;
x = fa[top[x]];
}
change(dfn[fx],tag);
// std::cout<<dfn[fx]<<" "<<tag<<std::endl;
change(dfn[x] + 1,-tag);
// std::cout<<dfn[x] + 1<<" "<<-tag<<std::endl;
}else{
ll ans = 0;
ll siza = cha(dfn[find(x)]),sizb = cha(dfn[y]);
ans = (siza - sizb) * sizb;
std::cout<<ans<<std::endl;
}
}
}