和 Ynoi 的题解思路一致,但实现略有不同。
#include<bits/stdc++.h>
#define sd std::
#define int long long
#define inf 0x3f3f3f3f
#define linf 1e18
#define il inline
#define db double
#define ldb long double
#define F(i,a,b) for(int i=(a);i<=(b);i++)
#define f(i,a,b) for(int i=(a);i>=(b);i--)
#define MIN(x,y) (x<y?x:y)
#define MAX(x,y) (x>y?x:y)
#define me(x,y) memset(x,y,sizeof x)
#define pii sd pair<int,int>
#define umap(x,y) sd unordered_map<x,y>
#define pque(x) sd priority_queue<x>
#define X first
#define Y second
#define kg putchar(' ')
#define Fr(a) for(auto it:a)
#define dbg(x) sd cout<<#x<<": "<<x<<sd endl
il int read(){int w=1,c=0;char ch=getchar();for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;for(;ch>='0'&&ch<='9';ch=getchar()) c=(c<<3)+(c<<1)+ch-48;return w*c;}
void printt(int x){if(x>9) printt(x/10);putchar(x%10+48);}
il void print(int x){if(x<0) putchar('-'),printt(-x);else printt(x);}
il void put(int x){print(x);putchar('\n');}
il void printk(int x){print(x);kg;}
const int N=1e5+10;
int n,m,c;
struct query
{
int id;
int x,y;
int flag;//类型
}q[N];
struct node
{
int nex;
int to;
}a[N];
int tot,head[N];
void add(int u,int v)
{
a[++tot].nex=head[u];
head[u]=tot;
a[tot].to=v;
}
int root,t,id[N],siz[N],fa[N],dep[N],son[N],top[N];
void dfs1(int u,int da)
{
dep[u]=dep[da]+1;
siz[u]=1;
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==da) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int da)
{
int v=son[u];
if(v)
{
id[v]=++t;
top[v]=top[u];
dfs2(v,u);
}
for(int i=head[u];i;i=a[i].nex)
{
int v=a[i].to;
if(v==da||v==son[u]) continue;
id[v]=++t;
top[v]=v;
dfs2(v,u);
}
}
#define ls k<<1
#define rs k<<1|1
int s[N<<2],lazy[N<<2];
void pushup(int k)
{
s[k]=s[ls]+s[rs];
}
void built(int k,int l,int r)
{
if(l==r) return s[k]=1,void();
int mid=l+r>>1;
built(ls,l,mid);
built(rs,mid+1,r);
}
void pushdown(int k,int l,int r)
{
if(!lazy[k]) return;
int mid=l+r>>1;
lazy[ls]+=lazy[k];
lazy[rs]+=lazy[k];
s[ls]+=(mid-l+1)*lazy[k];
s[rs]+=(r-mid)*lazy[k];
lazy[k]=0;
}
void update(int k,int l,int r,int x,int y,int v)
{
if(x<=l&&y>=r)
{
s[k]+=(r-l+1)*v;
lazy[k]+=v;
return;
}
pushdown(k,l,r);
int mid=l+r>>1;
if(x<=mid) update(ls,l,mid,x,y,v);
if(y>mid) update(rs,mid+1,r,x,y,v);
pushup(k);
}
int query(int k,int l,int r,int x,int y)
{
if(x<=l&&y>=r) return s[k];
pushdown(k,l,r);
int mid=l+r>>1,res=0;
if(x<=mid) res+=query(ls,l,mid,x,y);
if(y>mid) res+=query(rs,mid+1,r,x,y);
return res;
}
void upd_chain(int u,int v,int val)
{
int fu=top[u],fv=top[v];
while(fu!=fv)
{
if(dep[fu]<dep[fv]) sd swap(fu,fv),sd swap(u,v);
update(1,1,n,id[u],id[fu],val);
u=fa[fu];
fu=top[u];
}
if(dep[u]>dep[v]) sd swap(u,v);
update(1,1,n,id[u],id[v],val);
}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y){fa[find(x)]=find(y);}
il void solve()
{
n=read(),m=read();
built(1,1,n);
F(i,1,n) fa[i]=i;//并查集初始化
F(i,1,m)
{
char ch;
scanf("%c",&ch);
int x=read(),y=read();
if(ch=='A') q[i]={i,x,y,1},add(x,y),add(y,x);
else q[i]={i,x,y,0};
}
F(i,1,m)
{
if(q[i].flag) merge(q[i].x,q[i].y);
}
F(i,1,n) if(find(i)==i) add(n+1,i),add(i,n+1);
root=++n;//多一个虚点当根
dfs1(root,0);
id[root]=++t;top[root]=root;
dfs2(n,n+1);
F(i,1,n) fa[i]=i;
F(i,1,m)
{
int x=q[i].x,y=q[i].y;
if(fa[x]==y) sd swap(x,y);
if(q[i].flag)
{
upd_chain(x,find(x),query(1,1,n,y,y));
merge(x,y);
}
else
{
int sa=query(1,1,n,x,x),sb=query(1,1,n,y,y);
put((sa-sb)*sb);
}
}
}
signed main()
{
int T=1;
// T=read();
while(T--) solve();
return 0;
}