2019牛客暑期多校训练营(第九场) E All men are brothers
知识点:并查集+组合数学
并查集合并操作可以理解为使得两个集合的人互相成为朋友,也就是两个集合并在了一起,答案是要求从所有人中挑出四个互相不是朋友的四个人,比较基础的组合数学知识,但因为每个集合的大小预先不知,所以变得难以计算。

假设我们现在算出了合并前的答案,在合并x和y时,设 \(sz[x]\) 为\(x\)所在集合的集合大小,\(sz[y]\) 同理。考虑这两个集合对答案的贡献。有三种情况:
- 从x所在集合中取一个人,然后再从其他非y集合中挑选出三个互不在同一集合的人
- 从y所在集合中取一个人,然后再从其他非x集合中挑选出三个互不在同一集合的人
- 从x,y所在集合中各取一个人,然后再从其他集合中挑选出两个互不在同一集合的人
考虑合并之后

可以发现合并之后x和y在同一集合,仔细观察上面说到的情况1、2,它们对答案的贡献并没有因为合并操作而改变。只有情况3,在合并之后,该贡献被消灭,所以要用上一次的答案减去这个情况,就是合并之后的答案。
该怎么计算?情况3的答案等同于从非x,y的集合中挑两个集合并从这两个集合中各选一个人的情况总数。
举个例子,比如除去x,y所在的集合,剩下的集合的个数分别是
3 4 3 2
那么应该这么计算:
\((3*4 + 3*3 + 3 * 2) + (4*3+4*2) + (3*2)\)
等同于
\]
总人数为n,sum为每个集合大小的平方和,那么情况3的总数为
\]
然后 res -= num 更新答案即可
最后更新一下sum和 sz[x]或sz[y](取决于用哪个作为所在集合代表元素)
res初始化为\(C_n^4\)
由于n 是1e5,所以对n分情况讨论求\(C_n^4\)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
ll n,m;
ll fa[N],sz[N];
int find(int x){
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)fa[i] = i,sz[i] = 1ll;
if(n < 4){
printf("0\n");
while(m--){
int x,y;scanf("%d%d",&x,&y);
printf("0\n");
}
return 0;
}
ll res = 0;
if(n % 4 == 0){
res = n / 4 * (n-1) / 3 * (n-2) / 2 * (n-3);
}
else if(n % 4 == 1){
res = n * (n-1) / 4 * (n-2) / 3 * (n-3) / 2;
}
else if(n % 4 == 2){
res = n / 2 * (n-1) * (n-2) / 4 * (n-3) / 3;
}
else{
res = n / 3 * (n-1)/2 * (n-2) / 1 * (n-3)/4;
}
printf("%lld\n",res);
ll sum = n;
while(m--){
int x,y;
scanf("%d%d",&x,&y);
x = find(x);
y = find(y);
if(x == y){//如果已经在同一集合就不更新答案
printf("%lld\n",res);
continue;
}
sum -= sz[x] * sz[x];
sum -= sz[y] * sz[y];
res -= (sz[x] * sz[y]) * (((n - sz[x] - sz[y]) * (n - sz[x] - sz[y]) - sum)/2);
fa[x] = y;
sz[y] += sz[x];
sum += sz[y] * sz[y];
if(res < 0)res = 0;//res不能减成负数
printf("%lld\n",res);
}
return 0;
}
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 ...
随机推荐
- fenby C语言 P26
指针 地址 类型+“*”+变量名=指针变量 int *p1;//指向整型变量的指针变量p1 float *p2;//指向浮点型变量的指针变量p2 char *p3;//指向字符型变量的指针变量p3 “ ...
- 快速学习ggplot2
R语言里面一个比较重要的绘图包——ggplot2,是由Hadley Wickham于2005年创建,于2012年四月进行了重大更新,作者目前的工作是重写代码,简化语法,方便用户开发和使用.ggplot ...
- eclipse 工具翻译插件安装
http://download.eclipse.org/technology/babel/update-site/R0.15.1/oxygen
- [考试反思]1024csp-s模拟测试85:以为
愈发垃圾. T1基本全场切(除了RP<-inf的zkt和把人擦) 然后T2想了半天逐渐趋近于正解,但是因为数据有问题锅了25分,没什么好说的.T3连题意转化都没有完成.括号匹配转为+1/-1做法 ...
- CSPS模拟 85
WWB大佬的bitset映射真是太强了! %%% T1 观察样例,猜规律. T2 对题目的翻译工作用了很长时间 翻译错了好几次.. 观察到奇环没法染色,选的边必须把奇环弄断 如果在偶环上,偶环就变得没 ...
- UWP 带左右滚动按钮的横向ListView———仿NetFlix首页河的设计
也是之前写的控件了,模仿NetFlix的河的设计. 大体要求如下: 1. 横向的ListView 2. 左右按钮,可以左右移动河卡片,左右的滚动条不可见 3. 左右按钮仅在鼠标Hover事件中可见 大 ...
- python爬虫-携程-eleven参数
携程-eleven分析 一.eleven的位置 通过对旁边栈的分析,它是在另一个js文件中调用的.那个js文件是一个自调用的函数,所以我们可以直接copy下来,用浏览器执行看看 执行运行是会报错的,u ...
- C 总结 | 复习注意点
1.1 C预处理 常见错误 预处理错误 #include "" 和 <> 使用错误 "No such....." 更改“” 或者<> 或 ...
- Linux下安装nexus
下载地址:https://help.sonatype.com/repomanager3/download tar xf nexus-linux-3.19.1-01.tar.gz cd nexus-li ...
- linux日志查找方法
grep "xxxx" *201812* | grep "xxx" | awk -F, '{if(substr($1,1,10)=="2018-12- ...