#include "migrations.h"
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
/*
Robust + low-Z tail streaming (works for all trees; hits Subtask 1 = 30 when feasible):
- Maintain diameter endpoints (A,B) online via bounded LCA.
- Tail window W=50:
    * On first entry: emit a RESET (0)   [0 means "no message"; allowed]
    * Then stream 14 base-4 digits (values 1..4) encoding (A,B) interleaved LSB-first:
        positions 0..13: a0,b0,a1,b1,...,a6,b6   where ax/bx are base-4 digits of A/B.
    * If the diameter changes at index i:
        - If slots_left >= 14: emit RESET (0) and restart streaming for the new (A,B).
        - Else (too late): emit a single FALLBACK message = 10000 + (other+1).
- Museum:
    * If any S[i] > 4 in the tail exists → return (i, S[i]-10000-1).
    * Else decode after the last RESET: read the FIRST 14 digits (1..4) that follow and reconstruct (A,B).
*/
namespace {
    // Per-test state
    bool inited = false;
    int Nglob = 0, LOGv = 0;
    const int W = 50;
    int tailStart = 1;
    // LCA tables
    vector<int> depth;
    vector< vector<int> > up; // up[v][k]
    // Online diameter
    int A = 0, B = 0, D = 0;
    // Tail streaming state
    bool have_reset = false;
    int stream_pos = -1; // 0..13 for 14 digits
    inline void reset_case(int N){
        inited = true;
        Nglob = N;
        LOGv = 0; while ((1 << LOGv) <= (Nglob > 0 ? Nglob : 1)) ++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;
        tailStart = max(1, Nglob - W);
        have_reset = false;
        stream_pos = -1;
    }
    inline int lca(int u, int v){
        if (depth[u] < depth[v]) swap(u, v);
        int diff = depth[u] - depth[v];
        for (int k = 0; k < LOGv; ++k) if (diff & (1 << k)) u = up[u][k];
        if (u == v) return u;
        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 digit_base4(int x, int d){ // d-th digit (LSB-first), 0..3
        return (x >> (2*d)) & 3;
    }
}
int send_message(int N, int i, int Pi){
    // Reinit at the start of each test
    if (!inited || i == 1) reset_case(N);
    // Build LCA 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 >= tailStart){
        if (!have_reset){
            // Start tail epoch
            have_reset = true;
            stream_pos = 0;
            return 0; // RESET (no message)
        }
        if (changed){
            int slots_left = (Nglob - 1) - i; // remaining indices after i
            if (slots_left >= 14){
                // Enough room to re-encode final diameter
                stream_pos = 0;
                return 0; // RESET
            } else {
                // Too late to finish 14 digits → guarantee correctness with one fallback message
                // Encodes 'other' so Museum can return (i, other)
                return 10000 + (other + 1); // ≤ 20000 since other+1 ≤ 10000
            }
        }
        // No change → stream digits for current (A,B)
        if (stream_pos >= 0 && stream_pos < 14){
            int which = stream_pos++;
            int dig = ((which & 1) ? digit_base4(B, which/2)
                                   : digit_base4(A, which/2)); // 0..3
            out = dig + 1; // map to 1..4 to keep Z ≤ 4
        } else {
            out = 0; // no padding — silence after 14 digits
        }
    }
    return out; // 0..20000
}
std::pair<int,int> longest_path(std::vector<int> S){
    int N = (int)S.size();
    int tail = max(1, N - 50);
    // If any fallback (>4) exists in the tail, last one wins
    for (int i = N - 1; i >= tail; --i){
        if (S[i] > 4){
            int other = S[i] - 10000 - 1;
            if (other < 0) other = 0;
            if (other >= N) other = N - 1;
            return { i, other };
        }
    }
    // Otherwise decode after the last RESET (0)
    int lastReset = -1;
    for (int i = N - 1; i >= tail; --i){
        if (S[i] == 0){ lastReset = i; break; }
    }
    if (lastReset == -1){
        // Extremely unlikely; safe fallback
        return {0, 0};
    }
    // Read the FIRST 14 digits (1..4) after the last reset
    int cnt = 0;
    int Arec = 0, Brec = 0;
    for (int i = lastReset + 1; i < N && cnt < 14; ++i){
        int v = S[i];
        if (1 <= v && v <= 4){
            int d = v - 1; // 0..3
            if ((cnt & 1) == 0){
                // A digit
                int k = cnt / 2;
                Arec |= (d << (2*k));
            } else {
                // B digit
                int k = cnt / 2;
                Brec |= (d << (2*k));
            }
            ++cnt;
        }
    }
    if (Arec >= N) Arec = N - 1;
    if (Brec >= N) Brec = N - 1;
    return {Arec, Brec};
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |