• 2019牛客暑期多校训练营(第九场)E.All men are brothers(并查集+排列组合)


    题意:现在有n个集合 每个集合大小为1 现在你可以把集合合并m次 每次会告诉你哪个集合合并 让你输出每次从不同的四个集合里各选出四个的组合方案

    思路:我们可以想到用并查集模拟集合的合并 对于方案数 我们可以发现 其实就是合并之前的答案 减掉两个集合内的数的组合的方案数(详情理解代码)

    #include <bits/stdc++.h>
    using namespace std;
    const double pi = acos(-1.0);
    const int N = 1e6+7;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-6;
    typedef unsigned long long ll;
    const ll mod = 1e7+9;
    ll f[N],size[N];
    ll find(ll x){
        if(x!=f[x])
            f[x]=find(f[x]);
        return f[x];
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        ll n,m; cin>>n>>m;
        ll ans=(__int128)(n-1)*n/2*(n-2)*(n-3)/12; //组合数 
        for(ll i=0;i<N;i++){
            f[i]=i;
            size[i]=1;
        }
        ll sum=n; //记录有多少种两两组合的方案(这里是可重复的) 
        cout<<ans<<"
    ";
        for(ll i=1;i<=m;i++){
            ll x,y; cin>>x>>y;
            ll xx=find(x); ll yy=find(y);
            if(xx!=yy){
                sum-=(size[xx]*size[xx]);
                sum-=(size[yy]*size[yy]);
                ll tmp=size[xx]*size[yy]*((n-size[xx]-size[yy])*(n-size[xx]-size[yy])-sum)/2;
                f[xx]=yy;
                size[yy]+=size[xx];
                sum+=(size[yy]*size[yy]);
                ans-=tmp;            
            }
            cout<<ans<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    oracle-高级查询
    java-集合框架
    java-String-StringBuffer
    ROS消息, 服务, 主题, 订阅 5
    ROS消息, 服务, 主题, 订阅 4
    ROS消息, 服务, 主题, 订阅 3
    ROS消息, 服务, 主题, 订阅 2
    ROS消息, 服务, 主题, 订阅 1
    可交互的Marker
    RVIZ建Maker
  • 原文地址:https://www.cnblogs.com/wmj6/p/11359841.html
Copyright © 2020-2023  润新知