제출 #412672

#제출 시각아이디문제언어결과실행 시간메모리
412672KoD이상적인 도시 (IOI12_city)C++17
0 / 100
31 ms2040 KiB
#include <bits/stdc++.h> constexpr int MOD = 1000000000; template <class T> using Vec = std::vector<T>; struct UnionFind { Vec<int> par; std::stack<std::pair<int, int>> stack; UnionFind(const int n): par(n, -1), stack() {} int find(int u) const { while (par[u] >= 0) { u = par[u]; } return u; } int size(const int u) const { return -par[find(u)]; } int merge(int x, int y) { x = find(x); y = find(y); if (x == y) return 0; if (par[x] > par[y]) { std::swap(x, y); } stack.emplace(x, par[x]); stack.emplace(y, par[y]); par[x] += par[y]; par[y] = x; return 1; } void roll(int size) { size *= 2; while (size--) { const auto [i, v] = stack.top(); stack.pop(); par[i] = v; } } }; int solve(int N, int *X, int *Y) { std::map<int, Vec<std::pair<int, int>>> map; for (int i = 0; i < N; ++i) { map[X[i]].emplace_back(Y[i], i); } for (auto& [x, v]: map) { std::sort(v.begin(), v.end()); } UnionFind left(N), right(N); std::stack<int> roll; const auto try_find = [&](const int x, const int y) { const auto& vec = map[x]; auto itr = std::lower_bound(vec.cbegin(), vec.cend(), std::make_pair(y, 0)); if (itr == vec.cend() or itr -> first != y) { return -1; } return itr -> second; }; for (auto itr = map.rbegin(); itr != map.rend(); ++itr) { const auto& [x, v] = *itr; int sum = 0; for (int i = 1; i < (int) v.size(); ++i) { if (v[i - 1].first + 1 == v[i].first) { sum += right.merge(v[i - 1].second, v[i].second); } } for (const auto [y, u]: v) { const auto k = try_find(x + 1, y); if (k != -1) { sum += right.merge(u, k); } } roll.push(sum); } Vec<Vec<int>> graph(N); Vec<int> size(N); int ret = 0; for (const auto& [x, v]: map) { right.roll(roll.top()); roll.pop(); { for (int i = 1; i < (int) v.size(); ++i) { if (v[i - 1].first + 1 == v[i].first) { left.merge(v[i - 1].second, v[i].second); } } for (const auto [y, u]: v) { const auto k = try_find(x - 1, y); if (k != -1) { left.merge(u, k); } } } Vec<std::pair<int, int>> edge; { int last = -1; for (int i = 0; i < (int) v.size(); ++i) { if (last + 1 == v[i].first) { continue; } const auto k = try_find(x + 1, v[i].first); if (k != -1) { last = v[i].first; edge.emplace_back(left.find(v[i].second), right.find(k)); } } } if (edge.empty()) { continue; } for (const auto [x, y]: edge) { graph[x].push_back(y); graph[y].push_back(x); } Vec<int> coeff; auto dfs = [&](auto&& dfs, const int u, const int p) -> void { size[u] = (X[u] <= x ? left : right).size(u); for (const auto v: graph[u]) { if (v != p) { dfs(dfs, v, u); size[u] += size[v]; } } coeff.push_back(size[u]); }; const auto root = edge.front().first; dfs(dfs, root, -1); for (const auto x: coeff) { ret += (long long) x * (coeff.back() - x) % MOD; ret %= MOD; } for (const auto [x, y]: edge) { graph[x].clear(); graph[y].clear(); } } return ret; } int DistanceSum(int N, int *X, int *Y) { return (solve(N, X, Y) + solve(N, Y, X)) % MOD; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...