2019牛客暑期多校训练营(第九场) E-All men are brothers(并查集+组合数学)
题意:最初有 n个人且互不认识,接下来 m行,每行有 x,y表示x和y交朋友,朋友关系满足自反性和传递性,每次输出当前选取4个人且互不认识的方案数。
思路:比赛的时候知道是用并查集做,然而也只是知道,具体的思维还没有想到这一块,还是太菜了,得去多做多想~
并查集合并操作可以理解为使得两个集合的人互相成为朋友,也就是两个集合并在了一起,答案是要求从所有人中挑出四个互相不是朋友的四个人,比较基础的组合数学知识,但因为每个集合的大小预先不知,所以变得难以计算。
假设我们现在算出了合并前的答案,在合并x和y时,设 num[x]为x所在集合的集合大小,num[y] 同理。考虑这两个集合对答案的贡献,有三种情况:
- 从x所在集合中取一个人,然后再从其他非y集合中挑选出三个互不在同一集合的人
- 从y所在集合中取一个人,然后再从其他非x集合中挑选出三个互不在同一集合的人
- 从x,y所在集合中各取一个人,然后再从其他集合中挑选出两个互不在同一集合的人
考虑合并之后
可以发现合并之后x和y在同一集合,仔细观察上面说到的情况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(并查集+组合数学)的更多相关文章
- 2019牛客暑期多校训练营(第九场) D Knapsack Cryptosystem
题目 题意: 给你n(最大36)个数,让你从这n个数里面找出来一些数,使这些数的和等于s(题目输入),用到的数输出1,没有用到的数输出0 例如:3 4 2 3 4 输出:0 0 1 题解: 认真想一 ...
- 2019牛客暑期多校训练营(第二场) H-Second Large Rectangle(单调栈)
题意:给出由01组成的矩阵,求求全是1的次大子矩阵. 思路: 单调栈 全是1的最大子矩阵的变形,不能直接把所有的面积存起来然后排序取第二大的,因为次大子矩阵可能在最大子矩阵里面,比如: 1 0 0 1 ...
- 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题)
layout: post title: 2019牛客暑期多校训练营(第五场)G - subsequeue 1 (一题我真的不会的题) author: "luowentaoaa" c ...
- 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)
题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9: 对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可. 后者mod=1e9,5才 ...
- [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem
链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)
链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...
- 2019牛客暑期多校训练营(第一场) B Integration (数学)
链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...
- 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)
链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...
- 2019牛客暑期多校训练营(第二场)F.Partition problem
链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...
- 2019牛客暑期多校训练营(第八场)E.Explorer
链接:https://ac.nowcoder.com/acm/contest/888/E来源:牛客网 Gromah and LZR have entered the fifth level. Unli ...
随机推荐
- 明解C语言 入门篇 第二章答案
练习2-1 #include <stdio.h> int main() { int x; int y; int percent; puts("请输入两个整数"); pr ...
- 【XSY2985】【BZOJ1367】【Baltic2004】sequence
考虑两种情况: 1.\(a_1\)<\(a_2\)<\(a_3\)<\(a_4\)...<\(a_n\) 直接令\(b_i\)=\(a_i\),最小. 2.\(a_1\)> ...
- 学习笔记23_AspMVC项目
*创建AspMVC项目 (1)会自动创建App_Data文件夹,是用户不能访问和下载的.一般用户能访问那些文件夹,可以在IIS中配置. (2)App_Start文件夹,用于放置与程序有关的配置文件. ...
- [2018-06-28] 创建第一个django项目
1.创建一个名称为tmpl的项目 django-admin.py startproject tmpl 2.进入刚刚创建的tmpl目录 cd tmpl 3.创建一个名称为learn的应用 python ...
- ThinkPHP5.1 反序列化利用链
笔记里直接复制出来的 1 composer直接获取框架代码 ➜ composer create-project --prefer-dist topthink/think tp5137 ➜ ...
- CSPS模拟 82
还是Z哥的题,不过据说最后一题是D哥的 怪不得D2T3突然良心 (其实是突然毒瘤) 总分260大概是省三水平 不过和迪神并列了感觉还是很荣niu幸bi的- T1 考场上我弃了 因为是数学题,还要推柿子 ...
- python学习之【第六篇】:Python中的字典及其所具有的方法
1.前言 字典是python中唯一的映射类型,采用键值对(key-value)的形式存储数据.python对key进行哈希函数运算,根据计算的结果决定value的存储地址,因此,字典的key必须是可哈 ...
- P2579 [ZJOI2005]沼泽鳄鱼(邻接矩阵,快速幂)
题目简洁明了(一点都不好伐) 照例,化简题目 给一张图,每一个时间点有一些点不能走,(有周期性),求从起点第k秒恰好在终点的方案数,可重复,不可停留. 额dp实锤 于是就被打脸了.... 有一种东西叫 ...
- 考试T3麻将
这题就是一个简单的暴力,但考试的时候不知道脑子在想什么,什么都没打出来,也许是我想的太多了... 这道题对于不会打麻将的人来说还是有点难理解规则的,我没说过我会打麻将,这里是题目链接. 20分思路,利 ...
- CHRONY 时间服务器
时间同步服务chrony ntp network time Protocol之前使用的同步协议 chrony ntp协议的实现,兼容网络中的ntp服务(centos7之后就不再使用ntp,转而使用ch ...