Submission #1346113

#TimeUsernameProblemLanguageResultExecution timeMemory
1346113lucas110550Migrations (IOI25_migrations)C++20
65 / 100
23 ms1436 KiB
#include <vector>
#include <algorithm>
#include <utility>

namespace {
    // ----- global data kept only during the first run -------------
    std::vector<int> _depth;
    std::vector<std::vector<int>> _up;
    int _LOG = 0;
    
    int _a = 0, _b = 0, _diam = 0;
    int _N = 0;
    int _suffix_start = 0;
    const int _suffix_len = 28;

    // ----- auxiliary tree functions --------------------------------
    int _lca(int u, int v) {
        if (_depth[u] < _depth[v]) {
            std::swap(u, v);
        }
        // lift u to depth of v
        int diff = _depth[u] - _depth[v];
        int bit = 0;
        while (diff > 0) {
            if (diff & 1) {
                u = _up[u][bit];
            }
            diff >>= 1;
            bit++;
        }
        if (u == v) {
            return u;
        }
        // lift both while ancestors differ
        for (int k = _LOG - 1; k >= 0; k--) {
            if (_up[u][k] != _up[v][k]) {
                u = _up[u][k];
                v = _up[v][k];
            }
        }
        return _up[u][0]; // parent of u (or v)
    }

    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) {
    // ----- first call : initialise -----
    // Assuming the function is called for i = 1 .. N-1 in increasing order
    if (i == 1) {
        _N = N;
        
        // Calculate bit_length() + 1
        int temp = N;
        int bit_length = 0;
        while (temp > 0) {
            temp >>= 1;
            bit_length++;
        }
        _LOG = bit_length + 1;
        
        _depth.assign(N, 0);
        _up.assign(N, std::vector<int>(_LOG, -1));

        _a = 0;
        _b = 0;
        _diam = 0;

        // suffix of length 28 (if the tree is larger)
        if (N > _suffix_len) {
            _suffix_start = N - _suffix_len;
        } else {
            _suffix_start = 0;
        }
    }

    // ----- insert vertex i -----
    int p = Pi;
    _depth[i] = _depth[p] + 1;
    _up[i][0] = p;
    for (int k = 1; k < _LOG; k++) {
        int anc = _up[i][k - 1];
        _up[i][k] = (anc != -1) ? _up[anc][k - 1] : -1;
    }

    // ----- possibly enlarge the diameter -----
    int d1 = _dist(i, _a);
    if (d1 > _diam) {
        _b = i;
        _diam = d1;
    } else {
        int d2 = _dist(i, _b);
        if (d2 > _diam) {
            _a = i;
            _diam = d2;
        }
    }

    // ----- small N : encode everything in the last vertex -----
    if (_N <= _suffix_len) {
        if (i == _N - 1) {
            // encode (a , b) as a*(N+1) + b + 1
            return _a * (_N + 1) + _b + 1;
        }
        return 0;
    }

    // ----- large N : use the suffix -----
    if (i < _suffix_start) {
        return 0; // before the communication suffix
    }

    int offset = i - _suffix_start;       // 0 ... 27
    bool region_a = (offset < 14);        // a-bits part?
    bool region_b = !region_a;

    bool a_inside = (_a >= _suffix_start);
    bool b_inside = (_b >= _suffix_start);

    // marker for a ?
    if (a_inside && i == _a) {
        if (region_a) {
            return 2;
        } else {
            int b_bit = (_b < _suffix_start) ? ((_b >> (offset - 14)) & 1) : 0;
            return b_bit ? 3 : 2;
        }
    }

    // marker for b ?
    if (b_inside && i == _b) {
        if (region_b) {
            return 4;
        } else {
            int a_bit = (_a < _suffix_start) ? ((_a >> offset) & 1) : 0;
            return a_bit ? 5 : 4;
        }
    }

    // ordinary bit
    if (region_a) {
        if (_a < _suffix_start && ((_a >> offset) & 1)) {
            return 1;
        }
        return 0;
    } else {
        if (_b < _suffix_start && ((_b >> (offset - 14)) & 1)) {
            return 1;
        }
        return 0;
    }
}

// ------------------------------------------------------------
std::pair<int, int> longest_path(std::vector<int> S) {
    int N = S.size();

    // trivial tree of one vertex
    if (N == 1) {
        return {0, 0};
    }

    // small N - the answer was packed into a single number
    if (N <= 28) { // using literal instead of _suffix_len to keep it stateless
        int base = N + 1;
        int code = S[N - 1] - 1;
        int a = code / base;
        int b = code % base;
        return {a, b};
    }

    int suffix_start = N - 28;
    int a = -1; // -1 represents Python's None
    int b = -1;
    int bits_a = 0;
    int bits_b = 0;

    for (int offset = 0; offset < 28; offset++) {
        int i = suffix_start + offset;
        if (i >= N) {
            break;
        }
        
        int val = S[i];
        if (val == 0) {
            continue;
        }

        bool region_a = (offset < 14);
        bool region_b = !region_a;

        // ordinary bits
        if (val == 1) {
            if (region_a) {
                bits_a |= (1 << offset);
            } else {
                bits_b |= (1 << (offset - 14));
            }
            continue;
        }

        // markers for a
        if (val == 2 || val == 3) {
            a = i;
            if (region_b) { // a inside b-part -> b-bit is encoded
                if (val == 3) { // b-bit = 1
                    bits_b |= (1 << (offset - 14));
                }
            }
            continue;
        }

        // markers for b
        if (val == 4 || val == 5) {
            b = i;
            if (region_a) { // b inside a-part -> a-bit is encoded
                if (val == 5) { // a-bit = 1
                    bits_a |= (1 << offset);
                }
            }
            continue;
        }
    }

    if (a == -1) {
        a = bits_a;
    }
    if (b == -1) {
        b = bits_b;
    }

    return {a, b};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...