查询,就相当于先删去这条边,然后查询边的两个端点所在连通块大小,乘起来得到答案,然后再把边加回去
可以用线段树分治做
1 #pragma GCC optimize("Ofast") 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<map> 7 using namespace std; 8 #define fi first 9 #define se second 10 #define mp make_pair 11 #define pb push_back 12 typedef long long ll; 13 typedef unsigned long long ull; 14 typedef pair<int,int> pi; 15 #define N 100100 16 struct Q 17 { 18 int type,x,y,l,r,num; 19 }q[N*3]; 20 ll ans[N]; 21 int nq,n,qq,tm,an; 22 char ss[10]; 23 int fa[N],sz[N],dp[N]; 24 map<pi,int> ma; 25 int find(int x) 26 { 27 for(;x!=fa[x];x=fa[x]); 28 return x; 29 } 30 int bx[N*17],bfa[N*17],bsz[N*17],bdp[N*17],mem; 31 void unionn(int x,int y) 32 { 33 x=find(x),y=find(y); 34 ++mem;bx[mem]=x;bfa[mem]=fa[x];bsz[mem]=sz[x];bdp[mem]=dp[x]; 35 ++mem;bx[mem]=y;bfa[mem]=fa[y];bsz[mem]=sz[y];bdp[mem]=dp[y]; 36 if(dp[x]<dp[y]) {fa[x]=y;sz[y]+=sz[x];} 37 else 38 { 39 fa[y]=x;sz[x]+=sz[y]; 40 if(dp[x]==dp[y]) dp[x]++; 41 } 42 } 43 void backn(int nn) 44 { 45 for(int i=1;i<=nn;i++) 46 { 47 fa[bx[mem]]=bfa[mem];sz[bx[mem]]=bsz[mem];dp[bx[mem]]=bdp[mem];--mem; 48 fa[bx[mem]]=bfa[mem];sz[bx[mem]]=bsz[mem];dp[bx[mem]]=bdp[mem];--mem; 49 } 50 } 51 void solve(int pl,int pr,int l,int r)//[l,r]为线段树上区间 52 { 53 if(pl>pr) return; 54 int i,nn=0; 55 if(l==r) 56 { 57 for(i=pl;i<=pr;i++) 58 if(q[i].type==0) 59 unionn(q[i].x,q[i].y),++nn; 60 for(i=pl;i<=pr;i++) 61 if(q[i].type==1) 62 ans[q[i].num]=ll(sz[find(q[i].x)])*sz[find(q[i].y)]; 63 backn(nn); 64 return; 65 } 66 int mid=l+((r-l)>>1),p=pl-1; 67 for(i=pl;i<=pr;i++) 68 { 69 if(q[i].l<=l&&r<=q[i].r) unionn(q[i].x,q[i].y),++nn; 70 else if(q[i].l<=mid) swap(q[++p],q[i]); 71 } 72 solve(pl,p,l,mid);p=pl-1; 73 for(i=pl;i<=pr;i++) 74 { 75 if((q[i].l>l||r>q[i].r)&&mid<q[i].r) swap(q[++p],q[i]); 76 } 77 solve(pl,p,mid+1,r); 78 backn(nn); 79 } 80 int main() 81 { 82 int i,x,y; 83 scanf("%d%d",&n,&qq); 84 for(i=1;i<=qq;i++) 85 { 86 scanf("%s%d%d",ss,&x,&y); 87 if(x>y) swap(x,y); 88 if(ss[0]=='A') 89 { 90 ma[mp(x,y)]=++tm; 91 } 92 else 93 { 94 q[++nq]=(Q){0,x,y,ma[mp(x,y)],++tm,0}; 95 ++tm;q[++nq]=(Q){1,x,y,tm,tm,++an}; 96 ma[mp(x,y)]=++tm; 97 } 98 } 99 for(auto xx:ma) q[++nq]=(Q){0,xx.fi.fi,xx.fi.se,xx.se,tm,0}; 100 for(i=1;i<=n;i++) fa[i]=i,sz[i]=1; 101 solve(1,nq,1,tm); 102 for(i=1;i<=an;i++) printf("%lld ",ans[i]); 103 return 0; 104 }