제출 #1346068

#제출 시각아이디문제언어결과실행 시간메모리
1346068lucas110550이주 (IOI25_migrations)C++20
30 / 100
20 ms452 KiB
#include <vector>
#include <unordered_map>
#include <utility>
#include <algorithm>

// -------------------------------------------------------------
// Global state kept between successive calls of send_message
// -------------------------------------------------------------
std::vector<int> _depth;
int _max_depth = -1;
int _deepest = -1;
std::unordered_map<int, int> _pending;
bool _encoded = false;
bool _fallback = false;
int _L = 0;
int _suffix_start = 0;
bool _initialized = false;

int send_message(int N, int i, int Pi) {
    // ----- initialise on the first call -----
    if (!_initialized) {
        _depth.assign(N, 0);           // depth[0] = 0
        _max_depth = -1;
        _deepest = -1;
        _pending.clear();
        _encoded = false;
        _fallback = false;
        
        // smallest L with 3**L >= N
        _L = 0;
        long long power_of_3 = 1;
        while (power_of_3 < N) {
            _L++;
            power_of_3 *= 3;
        }
        _suffix_start = N - _L;
        _initialized = true;
    }

    // ----- compute depth of the current vertex -----
    int d = _depth[Pi] + 1;
    _depth[i] = d;

    // ----- update deepest vertex seen so far -----
    if (d > _max_depth) {
        _max_depth = d;
        _deepest = i;
    }

    // ----- already in fallback mode ? -----
    if (_fallback) {
        // send a message only from the current deepest vertex
        return (i == _deepest) ? 1 : 0;
    }

    // ----- a deeper vertex appears inside the suffix -> start fallback -----
    if (_deepest >= _suffix_start && i == _deepest) {
        _fallback = true;
        _pending.clear();              // cancel everything still pending
        return 1;                      // message for the deepest vertex
    }

    // ----- first position of the suffix, still normal mode -----
    if (i == _suffix_start && !_encoded) {
        if (_deepest < _suffix_start) { // deepest is before the suffix -> encode it
            _encoded = true;

            // base-3 representation, exactly _L digits (most significant first)
            std::vector<int> digits;
            int x = _deepest;
            for (int j = 0; j < _L; ++j) {
                digits.push_back(x % 3);
                x /= 3;
            }
            std::reverse(digits.begin(), digits.end());

            // first digit is sent now
            int first_val = digits[0] + 2; // 2, 3 or 4
            
            // schedule the remaining digits
            for (int offset = 1; offset < _L; ++offset) {
                _pending[_suffix_start + offset] = digits[offset] + 2;
            }
            return first_val;
        } else {
            // deepest already inside the suffix - nothing to encode
            return 0;
        }
    }

    // ----- inside the suffix while we are encoding -----
    if (_encoded) {
        auto it = _pending.find(i);
        if (it != _pending.end()) {
            int val = it->second;
            _pending.erase(it);       // scheduled digit (mimicking dict.pop)
            return val;
        } else {
            return 0;                 // all digits already sent
        }
    }

    // ----- no message to send -----
    return 0;
}


// ---------- second run ------------------------------------------------

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

    // recompute L (same as in the first run)
    int L = 0;
    long long power_of_3 = 1;
    while (power_of_3 < N) {
        L++;
        power_of_3 *= 3;
    }

    // locate the last non-zero entry
    int i_last = -1;
    for (int i = N - 1; i >= 0; --i) {
        if (S[i] != 0) {
            i_last = i;
            break;
        }
    }

    // according to the construction a non-zero entry always exists
    if (i_last == -1) {
        return {0, 0};
    }

    // fallback case - the special value 1 marks the deepest vertex
    if (S[i_last] == 1) {
        return {0, i_last};
    }

    // encoded suffix: collect the whole consecutive suffix of values >= 2
    std::vector<int> digits;
    int i = i_last;
    while (i >= 0 && S[i] >= 2) {
        digits.push_back(S[i] - 2);   // back to a base-3 digit (0, 1, 2)
        i--;
    }
    std::reverse(digits.begin(), digits.end()); // most-significant first

    // rebuild the vertex number
    int idx = 0;
    for (int d : digits) {
        idx = idx * 3 + d;
    }
    
    return {0, idx};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...