Submission #1274835

#TimeUsernameProblemLanguageResultExecution timeMemory
1274835mehrzad이주 (IOI25_migrations)C++17
10 / 100
35 ms1028 KiB
#include "migrations.h" #include <bits/stdc++.h> using namespace std; /* General solution (works for both subtasks): During the first run (send_message calls in increasing i): - We build the tree online and maintain binary-lifting parents (up[k][i]) and depths. - We maintain the current diameter endpoints (A, B) and its length D. For each new node i with parent p: * Compute dist(i, A) and dist(i, B) using LCA. * If dist(i, A) > D, set (B = i) and update D. * else if dist(i, B) > D, set (A = i) and update D. - We send exactly TWO messages total: * at i == N-2 we send A+1 * at i == N-1 we send B+1 (Each is ≤ N ≤ 10000 ≤ 20000, and M = 2 ≤ 50.) During the second run (longest_path): - Read the last two non-zero entries of S (order matters): * the penultimate non-zero is A+1, the last non-zero is B+1. - Return (A, B). This yields the true diameter for any tree (no need for the "root is an endpoint" assumption). */ // ---------------- Persistent state for the first run ---------------- namespace { constexpr int MAXN = 10000 + 5; constexpr int LOG = 15; // since 2^14 = 16384 > 10000 static bool initialized = false; static int depth_arr[MAXN]; static int up[LOG][MAXN]; // up[k][v] = 2^k-th ancestor of v, or -1 static int A = 0, B = 0; // current diameter endpoints static int D = 0; // current diameter length inline int lca(int u, int v) { if (u == -1 || v == -1) return u == -1 ? v : u; if (depth_arr[u] < depth_arr[v]) swap(u, v); int diff = depth_arr[u] - depth_arr[v]; for (int k = 0; k < LOG; ++k) if (diff & (1 << k)) u = up[k][u]; if (u == v) return u; for (int k = LOG - 1; k >= 0; --k) { if (up[k][u] != up[k][v]) { u = up[k][u]; v = up[k][v]; } } return up[0][u]; } inline int dist(int u, int v) { int w = lca(u, v); return depth_arr[u] + depth_arr[v] - 2 * depth_arr[w]; } inline void add_node(int i, int p) { // Set depth and ancestors for node i depth_arr[i] = depth_arr[p] + 1; up[0][i] = p; for (int k = 1; k < LOG; ++k) { int mid = up[k - 1][i]; up[k][i] = (mid == -1 ? -1 : up[k - 1][mid]); } // Try to improve diameter with endpoint A or B int dA = dist(i, A); if (dA > D) { B = i; D = dA; return; } int dB = dist(i, B); if (dB > D) { A = i; D = dB; return; } } } // ---------------- Research team procedure (first run) ---------------- int send_message(int N, int i, int Pi) { if (!initialized) { initialized = true; // Initialize root (node 0) depth_arr[0] = 0; for (int k = 0; k < LOG; ++k) up[k][0] = -1; // Start diameter as (0,0) A = 0; B = 0; D = 0; } // Add node i with parent Pi add_node(i, Pi); // Send two messages only at the last two sites if (i == N - 2) { return A + 1; // encode A } if (i == N - 1) { return B + 1; // encode B } return 0; } // ---------------- Museum procedure (second run) ---------------- std::pair<int,int> longest_path(std::vector<int> S) { // Extract the last two non-zero messages: penultimate -> A+1, last -> B+1 int N = (int)S.size(); int last_idx = -1, penult_idx = -1; for (int i = 1; i < N; ++i) { if (S[i] != 0) { penult_idx = last_idx; last_idx = i; } } if (last_idx == -1) { // No messages found; fallback to trivial answer return {0, 0}; } if (penult_idx == -1) { // Only one message found; interpret it as B+1 with A assumed 0 as a best-effort fallback int b = S[last_idx] - 1; if (b < 0) b = 0; return {0, b}; } int a = S[penult_idx] - 1; int b = S[last_idx] - 1; if (a < 0) a = 0; if (b < 0) b = 0; return {a, b}; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...