2019牛客暑期多校训练营(第九场)E All men are brothers(线段树做法)

链接:https://ac.nowcoder.com/acm/contest/889/E
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

Amy asks Mr. B  problem E. Please help Mr. B to solve the following problem.

There are n people, who don't know each other at the beginning.

There are m turns. In each turn, 2 of them will make friends with each other.

The friend relation is mutual and transitive.

If A is a friend of B, then B is also a friend of A.

For example, if A is a friend of B, B is a friend of C, then A and C are friends.

At the beginning and after each turn, please calculate the number of ways to select four people from, such that any two of these four are not friends.

输入描述:

The first line contains two integers, n and m (n <= 100000, m <= 200000), which are the number of people, and the number of turns.

In the following m lines, the i-th line contains two integers x and y ( 1 <= x <= n, 1 <= y <= n, x ≠ y), which means the x-th person and the y-th person make friends in the i-th turn.

The x-th person and y-th person might make friends in several turns.

输出描述:

Output m+1 lines, each line contains an integer, which is the number of quadruples.

Output at the beginning and after each turn, so there are m+1 lines.

示例1

输入

复制

6 6
1 2
3 4
4 5
3 5
3 6
2 4

输出

复制

15
9
4
0
0
0
0

示例2

输入

复制

100000 0

输出

复制

4166416671249975000

说明

Don't use int.

            因为组合较小(4),我们直接推两个集合融合的过程,然后加线段树支持单点修改就行了。

            推的过程字太丑,要是看代码不懂的话再留言或Q我吧。           

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int n, m;
const int maxn = 110000;
ll c[maxn * 8][5];
int fa[maxn], sz[maxn];
int fin(int x) {
	if (x != fa[x]) {
		fa[x] = fin(fa[x]);
	}
	return fa[x];
}
void pushup(int rt) {
	c[rt][1] = c[rt << 1][1] + c[rt << 1 | 1][1];
	c[rt][2] = c[rt << 1][1] * c[rt << 1 | 1][1] + c[rt << 1][2] + c[rt << 1 | 1][2];
	c[rt][3] = c[rt << 1][1] * c[rt << 1 | 1][2] + c[rt << 1][2] * c[rt << 1 | 1][1] 
		       + c[rt << 1][3] + c[rt << 1 | 1][3];
	c[rt][4] = c[rt << 1][2] * c[rt << 1 | 1][2] + c[rt << 1][1] * c[rt << 1 | 1][3] 
	           + c[rt << 1][3] * c[rt << 1 | 1][1] + c[rt << 1][4] + c[rt << 1 | 1][4];
}
void build(int l, int r, int rt) {
	if (l == r) {
		c[rt][4] = c[rt][3] = c[rt][2] = 0;
		c[rt][1] = 1;
		return;
	}
	int m = (l + r) >> 1;
	build(lson); build(rson);
	pushup(rt);
}
void add(int l, int r, int rt,int x,ll sum) {
	if (l == r) {
		c[rt][4] = c[rt][3] = c[rt][2] = 0;
		c[rt][1] = sum;
		return;
	}
	int m = (l + r) >> 1;
	if (x <= m) 
		add(lson, x, sum);
	else add(rson, x, sum);
	pushup(rt);
}
int main() {
	int n, m;
	ios::sync_with_stdio(0);
	cin >> n >> m;
	build(1, n, 1);
	for (int i = 1; i <= n; i++)
		fa[i] = i, sz[i] = 1;
	cout << c[1][4] << "\n";
	for (int i = 0; i < m; i++) {
		int a, b;
		cin >> a >> b;
		a = fin(a); b = fin(b);
		if (a != b) {
			fa[a] = b; sz[b] += sz[a];
			add(1, n, 1, a, 0);
			add(1, n, 1, b, sz[b]);
		}
		cout << c[1][4] << "\n";
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/chenshibo17/article/details/99649740
今日推荐