Submission #1250237

#TimeUsernameProblemLanguageResultExecution timeMemory
1250237chikien2009Making Friends on Joitter is Fun (JOI20_joitter2)C++20
100 / 100
856 ms103896 KiB
#include <bits/stdc++.h> using namespace std; void setup() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); } int par[100000], n, m, a, b; long long sz[100000], res; set<int> c[100000], g[100000], r[100000]; deque<pair<int, int>> edge; inline int Get(int inp) { return (inp == par[inp] ? inp : par[inp] = Get(par[inp])); } inline void Check(int ina, int inb) { g[ina].insert(inb); r[inb].insert(ina); if (g[inb].find(ina) != g[inb].end()) { edge.push_back({ina, inb}); } } inline int all(int inp) { return c[inp].size() + g[inp].size() + r[inp].size(); } inline void Combine(int ina, int inb) { ina = Get(ina); inb = Get(inb); if (ina == inb) { return; } if (all(ina) < all(inb)) { swap(ina, inb); } res += sz[ina] * c[inb].size() + sz[inb] * c[ina].size(); // part of A to child B and reverse sz[ina] += sz[inb]; par[inb] = ina; for (auto & i : c[inb]) { if (c[ina].find(i) != c[ina].end()) // if this node is child of both A and B, they're counted twice from above { res -= sz[ina]; } else { c[ina].insert(i); } } g[ina].erase(inb); g[inb].erase(ina); r[ina].erase(inb); r[inb].erase(ina); for (auto & i : g[inb]) { r[inb].erase(i); Check(ina, i); } for (auto & i : r[inb]) { g[inb].erase(i); Check(i, ina); } } int main() { setup(); cin >> n >> m; for (int i = 0; i < n; ++i) { par[i] = i; sz[i] = 1; c[i] = {i}; } while (m--) { cin >> a >> b; a--; b--; b = Get(b); if (Get(a) != b && c[b].find(a) == c[b].end()) { c[b].insert(a); res += sz[b]; a = Get(a); Check(a, b); while (!edge.empty()) { Combine(edge.front().first, edge.front().second); edge.pop_front(); } } cout << res << "\n"; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...