2019牛客多校E.All men are brothers(そして調査集+配列組合せ)
12544 ワード
連続エッジを並べて調べる過程を与え,連続エッジのたびに同じ集合内にない4つの選択法を選択する.
ごみ文科生はまた組み合わせられて授業を受けた.
まずこの問題は直接計算してもまったく計算できないので,1辺もないときの選び方がCn 4であることがわかりやすいので,毎回連辺の損失を計算することが考えられる.
では、連辺損失のたびに選ばれるのが、この2つのセット契約の時に人を選ぶ場合です.
どう計算しますか.まず、この2つの集合(k 1,k 2)を1人ずつ選択し、選択法は集合の大きさに乗算する.その後、残りの集合から2人を選択し、同一集合内から選択できないことを考慮しなければ、選択法はC(n-k 1-k 2)2であり、この組合せ数内のすべての同一集合内の選択法を減じる限り、残りの選択法である.この値は動的に維持でき,2つの集合を統合し,この2つの集合の共有を削減し,新しい集合の共有を加えるだけでよい.
ごみ文科生はまた組み合わせられて授業を受けた.
まずこの問題は直接計算してもまったく計算できないので,1辺もないときの選び方がCn 4であることがわかりやすいので,毎回連辺の損失を計算することが考えられる.
では、連辺損失のたびに選ばれるのが、この2つのセット契約の時に人を選ぶ場合です.
どう計算しますか.まず、この2つの集合(k 1,k 2)を1人ずつ選択し、選択法は集合の大きさに乗算する.その後、残りの集合から2人を選択し、同一集合内から選択できないことを考慮しなければ、選択法はC(n-k 1-k 2)2であり、この組合せ数内のすべての同一集合内の選択法を減じる限り、残りの選択法である.この値は動的に維持でき,2つの集合を統合し,この2つの集合の共有を削減し,新しい集合の共有を加えるだけでよい.
#include
using namespace std;
typedef unsigned long long ll;
const int maxn = 1e5 + 5;
int n, m;
int f[maxn];
ll sz[maxn];
ll ans, sum;
ll C2(ll x) {
if (x <= 1) {
return 0;
}
return x * (x - 1) / 2;
}
void init() {
for (int i = 1; i <= n; ++i) {
f[i] = i, sz[i] = 1;
}
}
int find(int x) {
if (x == f[x]) {
return x;
}
return f[x] = find(f[x]);
}
void merge(int x, int y) {
x = find(x), y = find(y);
if (x != y) {
int a = sz[x], b = sz[y];
ans = ans - (sz[x] * sz[y]) * (C2(n - sz[x] - sz[y]) - sum + C2(sz[x]) + C2(sz[y]));
sum = sum - C2(sz[x]) - C2(sz[y]);
sum = sum + C2(sz[x] + sz[y]);
f[y] = x;
sz[x] += sz[y];
}
}
int main() {
scanf("%d%d", &n, &m);
init();
ans = 1ULL * n * (n - 1) / 2 * (n - 2) / 3 * (n - 3) / 4;
printf("%llu
", ans);
int a, b;
while (m--) {
scanf("%d%d", &a, &b);
merge(a, b);
printf("%llu
", ans);
}
return 0;
}