RT 只有#1A了,剩的全WA
思路是线段树分治+可撤销并查集
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,cnt;
template<typename T,int siz> struct my_stack{
T st[siz];
int tp=0;
void push(T x){st[++tp]=x;}
void pop(){
if(!tp) cerr<<"THE STACK IS EMPTY!\n";
else tp--;
}
T top(){
if(!tp) cerr<<"THE STACK IS EMPTY!\n";
else return st[tp];
}
void clear(){tp=0;}
bool empty(){return !tp;}
};
struct del_tmp{int num,siz,d;};
template<int N>struct DSU{
int fa[N],siz[N],d[N];
void clear(int n){for(int i=1;i<=n;i++) fa[i]=i,siz[i]=1,d[i]=1;}
int find(int x){return (fa[x]==x?x:find(fa[x]));}
del_tmp merge(int x,int y){
int X=find(x),Y=find(y);
if(X==Y) return{0,0,0};
if(d[X]>d[Y]) swap(X,Y);
del_tmp ret={X,siz[X],d[X]==d[Y]};
d[Y]+=(d[X]==d[Y]),siz[Y]+=siz[X],fa[X]=Y;
return ret;
}
bool same(int x,int y){return find(x)==find(y);}
};
struct edge{
int u,v;
friend bool operator<(edge a,edge b){return a.u<b.u;}
}e[N],q[N];
vector<int>t[N];
map<edge,int>ma;
struct segment_tree{
DSU<N> dsu;
my_stack<del_tmp,N<<1>st;
segment_tree(){dsu.clear(N-1);}
struct segment_tree_node{vector<edge>v;}t[N<<2];
inline int ls(int x){return x<<1;};
inline int rs(int x){return x<<1|1;};
#define mid ((l+r)>>1)
void change(int p,int l,int r,int re_l,int re_r,edge val){
if(re_l<=l&&r<=re_r) return t[p].v.push_back(val),void();
else{
if(re_l<=mid) change(ls(p),l,mid,re_l,re_r,val);
if(mid<re_r) change(rs(p),mid+1,r,re_l,re_r,val);
}
}
void query(int p,int l,int r){
// cerr<<p<<" "<<l<<" "<<r<<"\n";
int tp=st.tp;
for(auto it:t[p].v) st.push(dsu.merge(it.u,it.v));
if(l==r){
if(q[l].u){
cerr<<l<<" "<<q[l].u<<" "<<q[l].v<<" "<<dsu.find(q[l].u)<<" "<<dsu.find(q[l].v)<<" "<<dsu.siz[dsu.find(q[l].u)]<<" "<<dsu.siz[dsu.find(q[l].v)]<<"\n";
cout<<1ll*dsu.siz[dsu.find(q[l].u)]*dsu.siz[dsu.find(q[l].v)]<<"\n";
}
}else query(ls(p),l,mid),query(rs(p),mid+1,r);
while(st.tp>tp){
del_tmp tmp=st.top();st.pop();
if(!tmp.num) continue;
dsu.siz[dsu.fa[tmp.num]]-=tmp.siz;
dsu.d[dsu.fa[tmp.num]]-=tmp.d;
dsu.fa[tmp.num]=tmp.num;
}
}
}T;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n>>m;
for(int i=1,u,v;i<=m;i++){
char opt;
cin>>opt>>u>>v;
if(u>v) swap(u,v);
if(opt=='A'){
e[++cnt]={u,v};
ma[{u,v}]=cnt;
t[cnt].push_back(i);
}else t[ma[{u,v}]].push_back(i),q[i]={u,v};
}
for(int i=1;i<=cnt;i++){
int last=0;
t[i].push_back(m+1);
for(auto it:t[i]){
cerr<<it<<" ";
if(last&&last!=m) T.change(1,1,m,last+1,it-1,e[i]);
last=it;
}
cerr<<"\n";
}
T.query(1,1,m);
}