Submission #766586

#TimeUsernameProblemLanguageResultExecution timeMemory
766586radoslav11Highway Tolls (IOI18_highway)C++17
0 / 100
14 ms1624 KiB
#include <bits/stdc++.h> #include "highway.h" using namespace std; tuple<vector<int>, vector<int>, vector<int>> bfs( int N, int M, vector<vector<pair<int, int>>> &adj, vector<int> srcs ) { vector<int> dist(N, -1); queue<int> q; for(int u : srcs) { dist[u] = 0; q.push(u); } vector<int> tree_edges; vector<int> cross_edges_mask(M, true); while(!q.empty()) { int u = q.front(); q.pop(); for(auto [v, i] : adj[u]) { if(dist[v] == -1) { dist[v] = dist[u] + 1; cross_edges_mask[i] = false; tree_edges.push_back(i); q.push(v); } } } vector<int> cross_edges; for(int i = 0; i < M; i++) { if(cross_edges_mask[i]) { cross_edges.push_back(i); } } return {dist, tree_edges, cross_edges}; } int find_first(vector<int> edges, int l, int r, int m, int64_t dist_heavy) { int found = -1, start = l; while(l <= r) { int mid = (l + r) >> 1; vector<int> mask(m, 1); for(int i = start; i <= mid; i++) { mask[edges[i]] = 0; } if(ask(mask) < dist_heavy) { r = mid - 1; found = mid; } else { l = mid + 1; } } return found; } pair<int, int> solve( vector<int> main_edge, int l, int r, int m, int64_t dist_heavy, int64_t dist_light ) { if(l == r) { return {l, -1}; } int mid = (l + r) >> 1; vector<int> mask(m, 1); for(int i = l; i <= mid; i++) { if(main_edge[i] != -1) { mask[main_edge[i]] = 0; } } int64_t dist_l = ask(mask); if(dist_l == dist_light) { return solve(main_edge, l, mid, m, dist_heavy, dist_light); } else if(dist_l == dist_heavy) { return solve(main_edge, mid + 1, r, m, dist_heavy, dist_light); } else { int s = find_first(main_edge, l, mid, m, dist_heavy); int t = find_first(main_edge, mid + 1, r, m, dist_heavy); return {s, t}; } } void find_pair(int N, std::vector<int> U, std::vector<int> V, int A, int B) { vector<vector<pair<int, int>>> adj; adj.assign(N, {}); for(int i = 0; i < (int)U.size(); i++) { adj[U[i]].push_back({V[i], i}); adj[V[i]].push_back({U[i], i}); } auto [dist, tree_edges, cross_edges] = bfs(N, U.size(), adj, {0}); // 1 query int64_t dist_heavy = ask(vector<int>(U.size(), 1)); // ceil(log2(M - N)) queries. Worst case 16 queries int found = find_first( cross_edges, 0, (int)cross_edges.size() - 1, U.size(), dist_heavy ); if(found != -1) { // reroot needed to guarantee that shortest path is on bfs tree auto [new_dist, new_tree_edges, _] = bfs(N, U.size(), adj, {U[cross_edges[found]], V[cross_edges[found]]}); new_tree_edges.push_back(found); tree_edges = new_tree_edges; dist = new_dist; } // 2 * ceil(log2(N) - 1) + 1 queries. // Worst case 33 queries vector<int> main_edge(N, -1); for(auto i : tree_edges) { int u = U[i], v = V[i]; if(dist[u] > dist[v]) { swap(u, v); } main_edge[v] = i; } int root = -1; for(int i = 0; i < N; i++) { if(main_edge[i] == -1) { root = i; } } int64_t dist_light = (dist_heavy / B) * A; auto [s, t] = solve(main_edge, 0, N - 1, U.size(), dist_heavy, dist_light); if(s == -1) { s = root; } if(t == -1) { t = root; } 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...