下面是我的代码,用的是线段树分治+可撤销并查集,在断边和建树过程中,我的右边界 r 设置成 m+10 就可以过,但设置成 m 就只有 40pts。为啥啊awa
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+7;
int n,m,cnt,tot,ans[N];
struct EDGE{
int u,v,s,t;
}e[N];
struct Q{
int t,x,y;
}q[N];
map<pair<int,int>,int> lst;
struct NODE{
int l,r;
vector<int> v;
vector<int> q;
}tr[N<<2];
void build(int p,int l,int r){
tr[p].l=l, tr[p].r=r;
tr[p].v.clear();
if(l==r) return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
void inse(int p,int l,int r,int i){
if(l<=tr[p].l && tr[p].r<=r){
tr[p].v.push_back(i);
return;
}
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid) inse(p<<1,l,r,i);
if(mid<r) inse(p<<1|1,l,r,i);
}
void insq(int p,int l,int i){//t=l插入询问i
if(tr[p].l == tr[p].r){
tr[p].q.push_back(i);
return;
}
int mid=(tr[p].l+tr[p].r)>>1;
if(l<=mid) insq(p<<1,l,i);
else insq(p<<1|1,l,i);
}
int fa[N],sz[N],high[N],tp;
struct ST{
int x,y,f,num;
//x->y, f=1表示深度+1了,num表示新增sz
}st[N];
int find(int x){
if(fa[x]==x) return x;
return find(fa[x]);
}
void merge(int x,int y){
x=find(x),y=find(y);
if(high[x]>high[y]) swap(x,y);
st[++tp]={x,y,(high[x]==high[y]),sz[x]};
fa[x]=y, sz[y]=sz[x]+sz[y];
if(high[x]==high[y]) high[y]++;
}
void solve(int p){
int nw=tp;
for(auto i:tr[p].v){//插入边
int u=e[i].u, v=e[i].v;
merge(u,v);
}
if(tr[p].l==tr[p].r){//叶子结点回答询问
for(auto i:tr[p].q){
int x=q[i].x, y=q[i].y;
x=find(x), y=find(y);
ans[q[i].t]=sz[x]*sz[y];
}
}
if(tr[p].l!=tr[p].r){
solve(p<<1);
solve(p<<1|1);
}
while(tp>nw){
sz[st[tp].y]-=st[tp].num;
high[st[tp].y]-=st[tp].f;
fa[st[tp].x]=st[tp].x;
tp--;
}
}
signed main(){
// freopen("P4219_2.in","r",stdin);
// freopen("P4219.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
fa[i]=i;
sz[i]=1;
high[i]=1;
}
for(int i=1;i<=m;i++){
char op; int x,y;
cin>>op>>x>>y;
if(x>y) swap(x,y);
if(op=='A'){
e[++cnt]={x,y,i,m+10};
lst[{x,y}]=cnt;
}else{
int p=lst[{x,y}];
e[p].t=i-1;
e[++cnt]={x,y,i+1,m+10};
lst[{x,y}]=cnt;
q[++tot]={i,x,y};//在i时刻有一个询问x,y
}
}
build(1,1,m+10);
for(int i=1;i<=cnt;i++){
inse(1,e[i].s,e[i].t,i);
}
for(int i=1;i<=tot;i++){
insq(1,q[i].t,i);
}
for(int i=1;i<=m;i++) ans[i]=-1;
solve(1);
for(int i=1;i<=m;i++){
if(ans[i]>=0) cout<<ans[i]<<'\n';
}
return 0;
}
/*
8 6
A 1 2
A 2 3
A 3 4
Q 2 3
A 2 5
Q 2 3
1_2 1_6
2_3 2_3
3_4 3_6
2_3 5_5
2_5 5_6
*/