>传送门<

题意:最初有 n个人且互不认识,接下来 m行,每行有 x,y表示xy交朋友,朋友关系满足自反性和传递性,每次输出当前选取4个人且互不认识的方案数。

思路:比赛的时候知道是用并查集做,然而也只是知道,具体的思维还没有想到这一块,还是太菜了,得去多做多想~

并查集合并操作可以理解为使得两个集合的人互相成为朋友,也就是两个集合并在了一起,答案是要求从所有人中挑出四个互相不是朋友的四个人,比较基础的组合数学知识,但因为每个集合的大小预先不知,所以变得难以计算。

假设我们现在算出了合并前的答案,在合并xy时,设 num[x]x所在集合的集合大小,num[y] 同理。考虑这两个集合对答案的贡献,有三种情况:

  1. x所在集合中取一个人,然后再从其他非y集合中挑选出三个互不在同一集合的人
  2. y所在集合中取一个人,然后再从其他非x集合中挑选出三个互不在同一集合的人
  3. x,y所在集合中各取一个人,然后再从其他集合中挑选出两个互不在同一集合的人

考虑合并之后

可以发现合并之后xy在同一集合,仔细观察上面说到的情况1、2,它们对答案的贡献并没有因为合并操作而改变。只有情况3,在合并之后,该贡献被消灭,所以要用上一次的答案减去这个情况,就是合并之后的答案

那么该怎么计算呢?情况3的答案等同于x,y所在集合中各取一个人的情况总数)*(从其他集合中挑选出两个互不在同一集合的人的情况总数

这两个集合中各选一个人的情况是很好求的:num[x]*num[y]。

好,现在就只剩下求从其他集合中挑选出两个互不在同一集合的人的情况总数,这一看就有点不好求,不要紧,我们开动脑瓜子想一想。

现在我们有两种做法,一种是直接求,一种是间接的求。

我们先来看直接求的那一种

我们假设K从所有集合中挑选出两个互不在同一集合的人的情况总数,那么我们用K减去从所有集合中挑选出两个互不在同一集合的人(其中至少有一个来自x或y),那么相减的结果不就是从其他集合中挑选出两个互不在同一集合的人的情况总数么,对不对,仔细想想肯定是这样的

那答案就出来了,如果x,y不需要合并的话(即在同一集合内),答案自然也就不需要更新,直接输出上一次的答案即可,其余部分按并查集处理就OK了

 Code

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+; int n, m, x, y;
int f[maxn];
ll num[maxn];
ll K; //K表示从所有集合中挑选2个互不在同一集合的人的方案数
unsigned long long C; //C表示从所有集合中挑选4个互不在同一集合的人的方案数
int get(int x){
if (f[x]==x) return x;
return f[x]=get(f[x]);
}
void unite(int a,int b){
ll p = num[a]*num[b]; //从a, b所在集合中各取1个人的情况
ll q = num[a]*(n-num[a])+num[b]*(n-num[b])-num[a]*num[b]; //从所有集合挑选2个人(至少有一个来自a或b)的情况
ll k = K-q; //再从其他集合中挑选2个互不在同一集合的人
C -= p*k;
K = K-num[a]*num[b]; //由于a, b集合合并,K减去在同一集合中选2个人的方案
f[a] = b;
num[b] += num[a];
}
void init(){
C=1ull*n*(n-)/*(n-)/*(n-)/; //C初始化为从所有数中选4个的方案总数
K = 1ll*n*(n-)/; //K初始化从所有数中选2个的方案总数
for (int i = ; i <= n; i++) f[i] = i, num[i] = ;
}
int main()
{
scanf("%d%d", &n, &m);
init();
printf("%llu\n",C);
while(m--){
scanf("%d%d",&x,&y);
if (get(x)!=get(y))
unite(f[x],f[y]);
printf("%llu\n",C);
}
}

参考文章:
https://www.cnblogs.com/1625--H/p/11359772.html

2019牛客暑期多校训练营(第九场) E-All men are brothers(并查集+组合数学)的更多相关文章

  1. 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem

    题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3  4 2 3 4 输出:0 0 1 题解: 认真想一 ...

  2. 2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)

    题意:给出由01组成的矩阵,求求全是1的次大子矩阵. 思路: 单调栈 全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如: 1 0 0 1 ...

  3. 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)

    layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...

  4. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  5. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  6. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  7. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  8. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  9. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  10. 2019牛客暑期多校训练营(第八场)E.Explorer

    链接:https://ac.nowcoder.com/acm/contest/888/E来源:牛客网 Gromah and LZR have entered the fifth level. Unli ...

随机推荐

  1. 小白初入Python人工智能

    想要了解人工智能首先要知道“百度大脑”(https://ai.baidu.com/?track=cp:aipinzhuan|pf:pc|pp:AIpingtai|pu:title|ci:|kw:100 ...

  2. django-模型之(ORM)对象关系映射(一)

    所谓对象关系映射,就是将数据库的一些名字与python中的一些名字相对应,表名-->类名,字段-->属性,操作(增删改查)-->方法.这样,我们就可以通过对Python代码的编辑来对 ...

  3. JavaScript随机生成布尔值

    //方法一 var rand = Boolean(Math.round(Math.random())); conosole.log(rand) // 方法二: var arr = [true,fals ...

  4. java中Arrays.sort()对二位数组进行排序

    int [][]a = new int [5][2]; //定义一个二维数组,其中所包含的一维数组具有两个元素 对于一个已定义的二位数组a经行如下规则排序,首先按照每一个对应的一维数组第一个元素进行升 ...

  5. 陈莉君教授: 回望踏入Linux内核之旅

    本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 陈莉君 来源: 微信公众号linux阅码场(id: linuxdev) 初次踏入Linux 几多耕耘,几多收获 ...

  6. 通俗地说逻辑回归【Logistic regression】算法(一)

    在说逻辑回归前,还是得提一提他的兄弟,线性回归.在某些地方,逻辑回归算法和线性回归算法是类似的.但它和线性回归最大的不同在于,逻辑回归是作用是分类的. 还记得之前说的吗,线性回归其实就是求出一条拟合空 ...

  7. 学习笔记63_python反射

    ####反射预备知识一########### __call__ 对象后面加括号,触发执行. python中,类的默认的内置方法,有一个名为__call__,如 class foo: def  __in ...

  8. FHQ treap学习(复习)笔记

    .....好吧....最后一篇学习笔记的flag它倒了..... 好吧,这篇笔记也鸽了好久好久了... 比赛前刷模板,才想着还是补个坑吧... FHQ,这个神仙(范浩强大佬),发明了这个神仙的数据结构 ...

  9. p4141(消失之物)

    题目描述 ftiasch 有 N 个物品, 体积分别是 W1, W2, …, WN. 由于她的疏忽, 第 i 个物品丢失了. “要使用剩下的 N – 1 物品装满容积为 x 的背包,有几种方法呢?” ...

  10. Subline Text3最新激活方法解决 That license key doesn't appear to be valid.

    第一步: 管理员身份登录系统 第二步: 进入到 C:\Windows\System32\drivers\etc (这个路径可以复制,都是一样的) 第三步: 右键hosts这个文件(打开方式 - 选择记 ...