题意:n个人,好友关系可以相互传递,每次给一个x和y让他们交朋友,问你每次交朋友后有多少选择能取出四个人,这四个人互不为好友
题解:用并查集维护集合大小,然后每次减去相应的组合数就可以
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
int pre[maxn],sum[maxn];
int n,m;
void init(){
for(int i=0;i<=n;i++)pre[i]=i,sum[i]=1;
}
int Find(int x){
return pre[x]==x?x:pre[x]=Find(pre[x]);
}
int main()
{
scanf("%d%d",&n,&m);
init();
ll ans=(__int128)n*(n-1)*(n-2)*(n-3)/4/3/2;
ll c2=(__int128)n*(n-1)/2;//n个人取两个
printf("%lld\n",ans);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
int fx=Find(x),fy=Find(y);
if(fx==fy){
printf("%lld\n",ans);
continue;
}
ull num=n-sum[fx]-sum[fy];
ull temp=c2-sum[fx]*num-sum[fy]*num-sum[fx]*sum[fy];//n个人取两个减去一个集合*一个外面,一个集合*一个外面,两个集合*,剩下的就是两个都是外面的
ans-=sum[fx]*sum[fy]*temp;//减去一个集合*一个集合*两个外面(可行方案),就是剩下的方案数
c2-=sum[fx]*sum[fy];//减去两个都在集合内,因为这两个合并了
pre[fx]=fy;
sum[fy]+=sum[fx];
printf("%lld\n",ans);
}
return 0;
}