传送门

知识点:并查集+组合数学

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

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

  1. 从x所在集合中取一个人,然后再从其他非y集合中挑选出三个互不在同一集合的人
  2. 从y所在集合中取一个人,然后再从其他非x集合中挑选出三个互不在同一集合的人
  3. 从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)\)

等同于

\[((3+4+3+2) * (3+4+3+2) - (3^2 + 4^2+3^2+2^2)) \over 2
\]

总人数为n,sum为每个集合大小的平方和,那么情况3的总数为

\[num = {(n-sz[x]-sz[y])^2-(sum-sz[x]^2-sz[y]^2)\over 2}
\]

然后 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的更多相关文章

  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. 设计模式C++描述----07.建造者(Builder)模式

    一. 概述 Builder 模式要解决的问题是:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要要复杂对象的创建过程和这个对象的表示(展示)分离开 来,这样做的好处就是通过一步 ...

  2. SpringBootCLI 命令行工具

    Spring Boot CLI 是用于快速开发 Spring 应用的命令行工具.用来运行 Groovy (与 Java 风格类似)脚本. spring-cli 似乎不是可以各种diy spring-b ...

  3. DB2中的MQT优化机制详解和实践

    MQT :物化查询表.是以一次查询的结果为基础  定义创建的表(实表),以量取胜(特别是在百万,千万级别的量,效果更显著),可以更快的查询到我们需要的结果.MQT有两种类型,一种是系统维护的MQT , ...

  4. CTR@因子分解机(FM)

    1. FM算法 FM(Factor Machine,因子分解机)算法是一种基于矩阵分解的机器学习算法,为了解决大规模稀疏数据中的特征组合问题.FM算法是推荐领域被验证效果较好的推荐算法之一,在电商.广 ...

  5. 使用Magicodes.SwaggerUI快速配置SwaggerUI以及设置API分组

    Magicodes.SwaggerUI 快速配置和集成SwaggerUI 特点 通过配置文件简单配置即可完成SwaggerUI的API格式JSON生成和集成 支持API分组和隐藏 支持自定义页面和验证 ...

  6. 面试精选:JVM垃圾回收

    Tips:关注公众号:松花皮蛋的黑板报,领取程序员月薪25K+秘籍,进军BAT必备! Java堆中存放着大量的Java对象实例,在垃圾收集器回收内存前,第一件事情就是确定哪些对象是“活着的”,哪些是可 ...

  7. Java基础语法01

    一.Java入门 Java 是最好的语言吗? 不是,因为在每个领域都有更合适的编程语言. Java技术体系平台 JavaSE//JavaEE//JavaME Java程序的结构 类{ 方法{ 语句; ...

  8. python入门三元运算

    三元运算又称三目运算,是对简单条件语句的简写: a = 1 b = 2 c = ' ' c = a  if  a > b  else b 在上面中首先判断a是否大于b如果为真则c = a,如果为 ...

  9. Centos 7环境下修改主机名

    步骤如下: 一.首先把虚拟机打开,用root账户进行登录后打开终端 二.我们看到我们虚拟机名称是默认的主机名. 三.用vi编辑器编辑etc目录下的hostname文件,输入“vi /etc/hostn ...

  10. Python3.7.1学习(一):redis的连接和简单使用

    1.python 利用 redis 第三方库 首先安装:pip install redis 2.reids的连接 Redis使用StrictRedis对象来管理对一个redis server 的所有连 ...