제출 #766372

#제출 시각아이디문제언어결과실행 시간메모리
766372boris_mihovHighway Tolls (IOI18_highway)C++17
51 / 100
172 ms262144 KiB
#include "highway.h" #include <algorithm> #include <iostream> #include <numeric> #include <cassert> #include <vector> #include <queue> typedef long long llong; const int MAXN = 90000 + 10; const int INF = 1e9; int n, m; int sz[MAXN]; int par[MAXN]; int parEdge[MAXN]; std::queue <int> q; std::vector <int> w; std::vector <std::pair <int,int>> g[MAXN]; std::queue <std::pair <int,int>> qDist; void initDFS(int node, int p) { sz[node] = 1; for (const auto &[u, idx] : g[node]) { if (u == p) { continue; } par[u] = node; parEdge[u] = idx; initDFS(u, node); sz[node] += sz[u]; } if (node == 1) { sz[node]--; } } int markEdges(int root, int cnt) { std::fill(w.begin(), w.end(), 0); if (cnt == 0) { return -1; } while (!q.empty()) { q.pop(); } q.push(root); int last = -1; if (root != 1) { w[parEdge[root]] = 1; last = parEdge[root]; cnt--; } while (cnt) { int top = q.front(); q.pop(); for (const auto &[u, idx] : g[top]) { if (cnt == 0) { break; } if (u == par[top]) { continue; } w[idx] = 1; last = idx; q.push(u); cnt--; } } return last; } std::vector <std::pair <int,int>> getKth(int node, int k) { assert(node != 1); w[parEdge[node]] = 1; std::vector <std::pair <int,int>> candidates; qDist.push({node, 1}); while (!qDist.empty()) { auto [top, dist] = qDist.front(); qDist.pop(); if (dist == k) { candidates.push_back({top, parEdge[top]}); continue; } for (const auto &[u, idx] : g[top]) { if (u == par[top]) { continue; } w[idx] = 1; qDist.push({u, dist + 1}); } } return candidates; } void find_pair(int N, std::vector <int> U, std::vector <int> V, int A, int B) { n = N; m = U.size(); for (int i = 0 ; i < m ; ++i) { U[i]++; V[i]++; g[U[i]].push_back({V[i], i}); g[V[i]].push_back({U[i], i}); } initDFS(1, 0); w.resize(m, 0); llong dist = ask(w) / A; int l = 0, r = n, mid, last = -1; while (l < r - 1) { mid = (l + r) / 2; int res = markEdges(1, mid); if (ask(w) == dist * A) l = mid; else { r = mid; last = res; } } assert(last != -1); if (U[last] == par[V[last]]) { std::swap(U[last], V[last]); } markEdges(U[last], sz[U[last]]); llong res = ask(w); llong distX = (res - dist * A) / (B - A); llong distY = dist - distX; std::fill(w.begin(), w.end(), 0); std::vector <std::pair <int,int>> candidates = getKth(U[last], distX); l = -1; r = candidates.size() - 1; while (l < r - 1) { mid = (l + r) / 2; for (const auto &[u, idx] : candidates) { w[idx] = 0; } for (int i = 0 ; i <= mid ; ++i) { w[candidates[i].second] = 1; } res = ask(w); if (res == distX * B + distY * A) r = mid; else l = mid; } int s, t; s = candidates[r].first; if (distY == 0) { answer(s - 1, V[last] - 1); return; } candidates.clear(); bool isGood = false; std::fill(w.begin(), w.end(), 0); for (const auto &[u, idx] : g[V[last]]) { if (u == par[V[last]]) { continue; } if (u == U[last]) { isGood = true; continue; } if (isGood) { std::vector <std::pair <int,int>> curr = getKth(u, distY); for (const auto &i : curr) { candidates.push_back(i); } } } l = -1, r = candidates.size() - 1; while (l < r - 1) { mid = (l + r) / 2; for (const auto &[u, idx] : candidates) { w[idx] = 0; } for (int i = 0 ; i <= mid ; ++i) { w[candidates[i].second] = 1; } res = ask(w); if (res == distX * A + distY * B) r = mid; else l = mid; } t = candidates[r].first; answer(s - 1, t - 1); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...