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 ...
随机推荐
- 设计模式C++描述----07.建造者(Builder)模式
一. 概述 Builder 模式要解决的问题是:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要要复杂对象的创建过程和这个对象的表示(展示)分离开 来,这样做的好处就是通过一步 ...
- SpringBootCLI 命令行工具
Spring Boot CLI 是用于快速开发 Spring 应用的命令行工具.用来运行 Groovy (与 Java 风格类似)脚本. spring-cli 似乎不是可以各种diy spring-b ...
- DB2中的MQT优化机制详解和实践
MQT :物化查询表.是以一次查询的结果为基础 定义创建的表(实表),以量取胜(特别是在百万,千万级别的量,效果更显著),可以更快的查询到我们需要的结果.MQT有两种类型,一种是系统维护的MQT , ...
- CTR@因子分解机(FM)
1. FM算法 FM(Factor Machine,因子分解机)算法是一种基于矩阵分解的机器学习算法,为了解决大规模稀疏数据中的特征组合问题.FM算法是推荐领域被验证效果较好的推荐算法之一,在电商.广 ...
- 使用Magicodes.SwaggerUI快速配置SwaggerUI以及设置API分组
Magicodes.SwaggerUI 快速配置和集成SwaggerUI 特点 通过配置文件简单配置即可完成SwaggerUI的API格式JSON生成和集成 支持API分组和隐藏 支持自定义页面和验证 ...
- 面试精选:JVM垃圾回收
Tips:关注公众号:松花皮蛋的黑板报,领取程序员月薪25K+秘籍,进军BAT必备! Java堆中存放着大量的Java对象实例,在垃圾收集器回收内存前,第一件事情就是确定哪些对象是“活着的”,哪些是可 ...
- Java基础语法01
一.Java入门 Java 是最好的语言吗? 不是,因为在每个领域都有更合适的编程语言. Java技术体系平台 JavaSE//JavaEE//JavaME Java程序的结构 类{ 方法{ 语句; ...
- python入门三元运算
三元运算又称三目运算,是对简单条件语句的简写: a = 1 b = 2 c = ' ' c = a if a > b else b 在上面中首先判断a是否大于b如果为真则c = a,如果为 ...
- Centos 7环境下修改主机名
步骤如下: 一.首先把虚拟机打开,用root账户进行登录后打开终端 二.我们看到我们虚拟机名称是默认的主机名. 三.用vi编辑器编辑etc目录下的hostname文件,输入“vi /etc/hostn ...
- Python3.7.1学习(一):redis的连接和简单使用
1.python 利用 redis 第三方库 首先安装:pip install redis 2.reids的连接 Redis使用StrictRedis对象来管理对一个redis server 的所有连 ...