結果
| 問題 | No.3200 Sinking Islands |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-01-22 16:19:53 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 305 ms / 2,000 ms |
| コード長 | 4,042 bytes |
| 記録 | |
| コンパイル時間 | 3,554 ms |
| コンパイル使用メモリ | 355,556 KB |
| 実行使用メモリ | 26,704 KB |
| 最終ジャッジ日時 | 2026-01-22 16:20:06 |
| 合計ジャッジ時間 | 10,250 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 20 |
ソースコード
#line 1 "3200.test.cpp"
#define PROBLEM "https://yukicoder.me/problems/no/3200"
#line 2 "ds/unionfind/unionfind.hpp"
#include <algorithm>
#include <numeric>
#include <vector>
struct UnionFind {
std::vector<int> parent, sz;
int num_comps;
UnionFind(int n = 0) { init(n); }
void init(int n) {
parent.resize(n);
iota(parent.begin(), parent.end(), 0);
sz.assign(n, 1);
num_comps = n;
}
int find(int x) { return (x == parent[x] ? x : parent[x] = find(parent[x])); }
bool same(int a, int b) { return find(a) == find(b); }
int size(int x) { return sz[find(x)]; }
bool join(int a, int b) {
a = find(a), b = find(b);
if (a != b) {
if (sz[a] < sz[b]) std::swap(a, b);
parent[b] = a;
sz[a] += sz[b];
num_comps--;
return true;
}
return false;
}
std::vector<std::vector<int>> groups() {
int n = parent.size();
std::vector<std::vector<int>> res(n);
std::vector<int> group_size(n, 0);
for (int i = 0; i < n; i++) {
group_size[find(i)]++;
}
std::vector<std::vector<int>> result;
std::vector<int> root_map(n, -1);
for (int i = 0; i < n; i++) {
int r = find(i);
if (root_map[r] == -1) {
root_map[r] = result.size();
result.push_back({});
result.back().reserve(group_size[r]);
}
result[root_map[r]].push_back(i);
}
return result;
}
};
#line 3 "3200.test.cpp"
#include <bits/stdc++.h>
using namespace std;
void solve() {
int64_t N, M;
cin >> N >> M;
UnionFind uf(N);
vector<array<int, 2>> Edges(M);
multiset<array<int, 2>> st;
for (int i = 0; i < M; i++) {
cin >> Edges[i][0] >> Edges[i][1];
Edges[i][0]--, Edges[i][1]--;
if (Edges[i][0] > Edges[i][1]) {
swap(Edges[i][0], Edges[i][1]);
}
st.insert({Edges[i][0], Edges[i][1]});
}
int Q;
cin >> Q;
vector<int> query(Q);
for (int i = 0; i < Q; i++) {
int num_edge;
cin >> num_edge;
num_edge--;
query[i] = num_edge;
auto it = st.find(Edges[num_edge]);
st.erase(it);
}
vector<int64_t> ans;
for (auto &[u, v] : st) {
uf.join(u, v);
}
reverse(query.begin(), query.end());
int64_t connected = 0, tot = N * (N - 1) / 2;
auto group = uf.groups();
for (auto &root : group) {
int64_t now = (int64_t)root.size();
connected += now * (now - 1) / 2;
}
for (auto &num_edge : query) {
ans.push_back(tot - connected);
int par1 = uf.find(Edges[num_edge][0]), par2 = uf.find(Edges[num_edge][1]);
int64_t size1 = uf.sz[par1], size2 = uf.sz[par2];
if (par1 != par2) {
connected -= (size1 * (size1 - 1) / 2 + size2 * (size2 - 1) / 2);
int64_t new_size = size1 + size2;
connected += new_size * (new_size - 1) / 2;
}
uf.join(par1, par2);
}
reverse(ans.begin(), ans.end());
for (auto &x : ans) {
cout << x << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}