Submission #499654

#TimeUsernameProblemLanguageResultExecution timeMemory
499654CatalinTHighway Tolls (IOI18_highway)C++17
51 / 100
323 ms262148 KiB
#include <map> #include <unordered_map> #include <unordered_set> #include <set> #include <vector> #include <numeric> #include <algorithm> #include <iostream> #include <string> #include <cstring> #include <sstream> #include <functional> #include <queue> #include <deque> #include <stack> #include <cassert> #include <iomanip> #include <cmath> #include <bitset> using namespace std; #include "highway.h" using int64 = long long; // cache map<pair<int, int>, int> eidx; int eget(int u, int v) { if (u > v) swap(u, v); return eidx[{u, v}]; } void eset(int u, int v, int idx) { if (u > v) swap(u, v); eidx[{u, v}] = idx; } // vector<vector<int>> adj; vector<int> dist; vector<int> par; void dfs(int n, int p) { for (int v : adj[n]) { if (v != p) { dist[v] = dist[n] + 1; par[v] = n; dfs(v, n); } } } void find_pair(int N, std::vector<int> U, std::vector<int> V, int A, int B) { int M = U.size(); int S = -1; int T = -1; // Step 0. Find min dist, 1 query vector<int> w(M); int64 D = ask(w) / A; // Step 1. Find edge on min - path, 18 queries worst-case (!) int l = 0, r = M - 1, sol = -1; while (l <= r) { int m = (l + r) >> 1; w.assign(M, 0); for (int i = 0; i <= m; i++) w[i] = 1; int64 cur = ask(w); if (cur > D * A) { sol = m; r = m - 1; } else { l = m + 1; } } assert(sol != -1); cerr << "Critical edge: " << U[sol] << " -> " << V[sol] << "\n"; // 51 points, tree adj.assign(N, vector<int>{}); for (int i = 0; i < M; i++) { adj[ U[i] ].push_back( V[i] ); adj[ V[i] ].push_back( U[i] ); eset(U[i], V[i], i); } auto solve_half_tree = [&] (int x, int y, int & R) { R = -1; cerr << "solve_half_tree, start: " << x << " par: " << y << "\n"; dist.assign(N, 0); par.assign(N, -1); dfs(x, y); w.assign(M, 0); for (int i = 0; i < N; i++) { if (par[i] != -1) { w[eget(i, par[i])] = 1; } } int64 depth = ask(w); bool ok = false; for (int i = 0; i < N; i++) { if ((int64)i * B + (int64)(D - i) * A == depth) { depth = i; ok = true; break; } } assert(ok); cerr << "depth: " << depth << "\n"; if (!depth) { R = x; } else { vector<int> cand; for (int i = 0; i < N; i++) { if (par[i] != -1 && dist[i] == depth) { cand.push_back(i); } } assert(cand.size()); function<int(int, int)> rec = [&] (int l, int r) { if (l == r) { return cand[l]; } int m = (l + r) >> 1; vector<int> w(M); for (int i = l; i <= m; i++) { w[eget(cand[i], par[cand[i]])] = 1; } bool ok = ask(w) > D * A; if (ok) { return rec(l, m); } else { return rec(m + 1, r); } }; R = rec(0, cand.size() - 1); }; }; solve_half_tree(U[sol], V[sol], S); solve_half_tree(V[sol], U[sol], T); cerr << S << " " << T << "\n"; assert(S != T); answer(S, T); }
#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...