Submission #1283355

#TimeUsernameProblemLanguageResultExecution timeMemory
1283355feining_for_gmMeetings (JOI19_meetings)C++20
29 / 100
392 ms1012 KiB
// meetings.cpp #include <bits/stdc++.h> #include "meetings.h" using namespace std; // ---------- Utilities ---------- static inline long long keyEdge(int u, int v) { if (u > v) swap(u, v); return ( (long long)u << 21 ) ^ (long long)v; // N <= 2000 fits well } struct Reconstructor { int N; vector<vector<int>> adj; // for optional internal checks (not needed by grader) unordered_set<long long> edge_set; // to avoid duplicate Bridge calls Reconstructor(int n): N(n) { adj.assign(N, {}); edge_set.reserve(2*N); } // Safely add one real edge (u,v) once. void add_edge(int u, int v) { if (u > v) swap(u, v); long long k = keyEdge(u, v); if (edge_set.insert(k).second) { // Record edge for sanity (optional) adj[u].push_back(v); adj[v].push_back(u); } } // Projection of x onto path (A,B). Avoids duplicate-node queries. int project(int A, int B, int x) { if (x == A) return A; if (x == B) return B; return Query(A, B, x); } // Find diameter endpoints of set S (one pass, ~|S|-2 queries). pair<int,int> find_diameter(const vector<int>& S) { int a = S[0]; int b = S[1 % (int)S.size()]; for (int i = 0; i < (int)S.size(); ++i) { int x = S[i]; if (x == a || x == b) continue; int p = project(a, b, x); if (p == a) a = x; else if (p == b) b = x; // else x is inside current path; ignore } return {a, b}; } // Comparator to order nodes u,v that we know lie on path A-B: // u comes before v from A towards B iff Query(A,u,v) == u. struct PathLess { int A; PathLess(int A): A(A) {} bool operator()(int u, int v) const { if (u == v) return false; if (u == A) return true; if (v == A) return false; int m = Query(A, u, v); return m == u; // u is between A and v => u is closer to A than v } }; void build_on_set(const vector<int>& S) { if ((int)S.size() <= 1) return; // 1) Find diameter endpoints (A,B) auto pr = find_diameter(S); int A = pr.first, B = pr.second; // 2) Project everything onto A-B, split into on-path and buckets vector<int> onpath; onpath.reserve(S.size()); unordered_map<int, vector<int>> bucket; // projection point -> nodes hanging there bucket.reserve(S.size()*2); for (int x : S) { int p; if (x == A || x == B) { p = x; // avoid duplicate-node query } else { p = project(A, B, x); } if (p == x) { onpath.push_back(x); } else { bucket[p].push_back(x); } } // 3) Sort path nodes from A to B using median comparator // (A will naturally be first due to the comparator handling) sort(onpath.begin(), onpath.end(), PathLess(A)); // 4) Add edges along this path (consecutive nodes are adjacent in the real tree) for (int i = 0; i + 1 < (int)onpath.size(); ++i) { add_edge(onpath[i], onpath[i+1]); } // 5) Recurse on each hanging component {t} ∪ bucket[t] for (int t : onpath) { auto it = bucket.find(t); if (it == bucket.end() || it->second.empty()) continue; vector<int> sub; sub.reserve(it->second.size() + 1); sub.push_back(t); for (int v : it->second) sub.push_back(v); build_on_set(sub); } } void run() { // Start with the full set of nodes vector<int> all(N); iota(all.begin(), all.end(), 0); build_on_set(all); // At this point we should have exactly N-1 distinct edges. // Report them via Bridge(u,v). // (The grader requires exactly N-1 calls, all correct and unique.) // For determinism, iterate through adjacency or through the set. // We'll iterate through the set we maintained. vector<pair<int,int>> edges; edges.reserve(N-1); edges.clear(); for (long long k : edge_set) { int u = (int)(k >> 21); int v = (int)(k & ((1<<21)-1)); edges.emplace_back(u, v); } // Sanity: ensure exactly N-1 // (If not, still output what we have; the grader will judge.) // But the algorithm constructs exactly N-1 unique edges. for (auto &e : edges) { Bridge(e.first, e.second); } } }; void Solve(int N) { Reconstructor rec(N); rec.run(); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...