Submission #1275583

#TimeUsernameProblemLanguageResultExecution timeMemory
1275583mehrzadMigrations (IOI25_migrations)C++17
0 / 100
30 ms1168 KiB
#include "migrations.h"
#include <bits/stdc++.h>
using namespace std;

/*
Robust, low-chatter, unambiguous protocol.

—we maintain the current diameter (A,B) online with LCA.
—we only transmit in the last K=50 insertions: startIdx = max(1, N-K).
—on a REAL diameter change at i, we send EVEN = (other_endpoint + 1) forced even.
—otherwise (no change), we send exactly TWO ODD inits once in the suffix:
     1) (A + 1) forced odd
     2) (B + 1) forced odd (skipped if a change happens before sending it)

Museum decoding:
—if any EVEN message exists, take the LAST EVEN → (U = that i, V = value-1).
—else take the LAST TWO ODD messages → (U = odd1-1, V = odd2-1).

Key fix vs. previous attempts: LCA lifting loops are BOUNDED by LOGv.
*/

namespace {
    // per-test state
    bool inited = false;
    int Nglob = 0, LOGv = 0;
    int K = 50, startIdx = 1;

    vector<int> depth;
    vector<vector<int>> up; // up[v][k], k in [0..LOGv-1]

    int A = 0, B = 0, D = 0;           // current diameter endpoints and length

    bool sentInit1 = false, sentInit2Pending = false;
    int init2Val = 0;

    inline void reset_test(int N){
        inited = true;
        Nglob = N;
        LOGv = 0; while ((1 << LOGv) <= max(1, Nglob)) ++LOGv;
        depth.assign(Nglob, 0);
        up.assign(Nglob, vector<int>(LOGv, 0));
        for (int k = 0; k < LOGv; ++k) up[0][k] = 0;

        A = B = 0; D = 0;
        K = min(50, max(1, Nglob - 1));
        startIdx = max(1, Nglob - K);

        sentInit1 = false;
        sentInit2Pending = false;
        init2Val = 0;
    }

    inline int lca(int u, int v){
        if (depth[u] < depth[v]) swap(u, v);
        int diff = depth[u] - depth[v];
        // lift u by bounded bits of diff
        for (int k = 0; k < LOGv; ++k){
            if (diff & (1 << k)) u = up[u][k];
        }
        if (u == v) return u;
        // jump both up
        for (int k = LOGv - 1; k >= 0; --k){
            if (up[u][k] != up[v][k]){
                u = up[u][k];
                v = up[v][k];
            }
        }
        return up[u][0];
    }

    inline int dist(int u, int v){
        int w = lca(u, v);
        return depth[u] + depth[v] - 2 * depth[w];
    }

    inline int force_even(int x){ return (x & 1) ? x + 1 : x; }
    inline int force_odd (int x){ return (x & 1) ? x     : x + 1; }
}

int send_message(int N, int i, int Pi){
    // Reinit per test when i==1 (new test case)
    if (!inited || i == 1) reset_test(N);

    // Fill lifting info for node i
    depth[i] = depth[Pi] + 1;
    up[i][0] = Pi;
    for (int k = 1; k < LOGv; ++k) up[i][k] = up[ up[i][k-1] ][k-1];

    // Online diameter update
    int dA = dist(i, A);
    int dB = dist(i, B);
    bool changed = false;
    int other = -1;
    if (dA > D){ changed = true; other = A; B = i; D = dA; }
    else if (dB > D){ changed = true; other = B; A = i; D = dB; }

    int out = 0;
    if (i >= startIdx){
        if (changed){
            // Real change → EVEN-coded other+1
            int v = other + 1;          // 1..N ≤ 10000
            v = force_even(v);          // make it even to mark "change"
            // v ≤ 10000, so ≤ 20000 bound always satisfied
            out = v;
            // once a real change occurs, we skip pending init2
            sentInit2Pending = false;
        } else if (!sentInit1){
            // First init → ODD-coded A+1
            int v = force_odd(A + 1);
            out = v;
            sentInit1 = true;
            sentInit2Pending = true;
            init2Val = force_odd(B + 1);
        } else if (sentInit2Pending){
            // Second init → ODD-coded B+1
            out = init2Val;
            sentInit2Pending = false;
        }
        // else: stay silent
    }
    return out; // 0 = no message
}

std::pair<int,int> longest_path(std::vector<int> S){
    // Collect nonzero messages
    vector<pair<int,int>> msgs;
    msgs.reserve(S.size());
    for (int i = 0; i < (int)S.size(); ++i)
        if (S[i] != 0) msgs.emplace_back(i, S[i]);

    if (msgs.empty()) return {0, 0}; // degenerate tiny trees

    // Prefer the last EVEN message → final real change
    for (int t = (int)msgs.size() - 1; t >= 0; --t){
        if ((msgs[t].second & 1) == 0){
            int idx = msgs[t].first;
            int v = msgs[t].second - 1; // decode other endpoint
            return { idx, v };
        }
    }
    // Otherwise, use the last two ODD messages (the two init endpoints)
    int found = 0;
    int v_last = -1, v_prev = -1;
    for (int t = (int)msgs.size() - 1; t >= 0 && found < 2; --t){
        if ((msgs[t].second & 1) == 1){
            if (found == 0) v_last = msgs[t].second - 1;
            else            v_prev = msgs[t].second - 1;
            ++found;
        }
    }
    if (found == 2) return { v_prev, v_last };

    // Fallback: single odd message — interpret as (idx, val-1)
    auto [idx, val] = msgs.back();
    return { idx, val - 1 };
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...