Submission #1339205

#TimeUsernameProblemLanguageResultExecution timeMemory
1339205lucas110550Migrations (IOI25_migrations)C++20
22.09 / 100
29 ms1080 KiB
#include <vector>
#include <utility>
#include <algorithm>

// Global state variables
static int _N = 0;
static std::vector<int> _depth;
static std::vector<std::vector<int>> _up;
static int _LOG = 0;
static int _a = 0;
static int _b = 0;
static int _diam = 0;
static int _a2 = -1;      // using -1 for Python's None
static int _b2 = -1;
static int _b_at_N3 = -1;

void _reinit(int N) {
    _N = N;
    
    // Equivalent to Python's N.bit_length() + 1
    int temp = N;
    int bits = 0;
    while (temp > 0) {
        bits++;
        temp >>= 1;
    }
    _LOG = bits + 1;
    
    _depth.assign(N, 0);
    _up.assign(_LOG, std::vector<int>(N, 0));
    _a = 0;
    _b = 0;
    _diam = 0;
    _a2 = -1;
    _b2 = -1;
    _b_at_N3 = -1;
}

int _lca(int u, int v) {
    if (_depth[u] < _depth[v]) {
        std::swap(u, v);
    }
    int diff = _depth[u] - _depth[v];
    int bit = 0;
    while (diff > 0) {
        if (diff & 1) {
            u = _up[bit][u];
        }
        diff >>= 1;
        bit++;
    }
    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];
}

int _dist(int u, int v) {
    int w = _lca(u, v);
    return _depth[u] + _depth[v] - 2 * _depth[w];
}

int send_message(int N, int i, int Pi) {
    // Initialise a fresh test case at the first call (i == 1)
    if (i == 1) {
        _reinit(N);
    }

    // ---- insert new leaf i ----
    int d = _depth[Pi] + 1;
    _depth[i] = d;
    _up[0][i] = Pi;
    for (int k = 1; k < _LOG; ++k) {
        int anc = _up[k - 1][i];
        _up[k][i] = _up[k - 1][anc];
    }

    // ---- maintain the current diameter (a,b) ----
    int da = _dist(i, _a);
    int db = _dist(i, _b);
    if (da > _diam) {
        _b = i;
        _diam = da;
    } else if (db > _diam) {
        _a = i;
        _diam = db;
    }

    // ---- decide which messages to send (only three are needed) ----
    if (_N >= 4 && i == _N - 3 && i >= 1) {
        _b_at_N3 = _b;
        return _b + 1;
    } else if (i == _N - 2 && i >= 1) {
        _a2 = _a;
        _b2 = _b;
        return _a + 1;
    } else if (i == _N - 1 && i >= 1) {
        int a_final = _a;
        int b_final = _b;
        int a2 = _a2;
        int b2 = _b2;
        int b0 = _b_at_N3;
        
        int flag = 0;

        // Determine which case we are in and assign the flag.
        if (a_final == a2 && b_final == b2) {
            if (b2 == _N - 2) {
                flag = 2;
            } else {
                flag = 1;
            }
        } else if (a_final == a2 && b_final == _N - 1) {
            flag = 3;
        } else if (a_final == _N - 1 && b_final == b2) {
            if (b2 == _N - 2) {
                flag = 5;
            } else {
                flag = 4;
            }
        } else {
            flag = 1;
        }

        return flag;
    } else {
        return 0;
    }
}

std::pair<int, int> longest_path(std::vector<int> S) {
    int N = S.size();
    if (N <= 1) {
        return {0, 0};
    }
    if (N == 2) {
        return {0, 1};
    }
    if (N == 3) {
        return {1, 2};
    }

    int a_msg = S[N - 2];
    int b_msg = S[N - 3];
    int flag = S[N - 1];

    int a = a_msg - 1;
    int b0 = b_msg - 1;
    
    int u = 0, v = 0;

    if (flag == 1) {
        u = a;
        v = b0;
    } else if (flag == 2) {
        u = a;
        v = N - 2;
    } else if (flag == 3) {
        u = a;
        v = N - 1;
    } else if (flag == 4) {
        u = b0;
        v = N - 1;
    } else if (flag == 5) {
        u = N - 2;
        v = N - 1;
    } else {
        u = a;
        v = b0;
    }
    
    return {u, v};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...