제출 #1335589

#제출 시각아이디문제언어결과실행 시간메모리
1335589lucas110550이주 (IOI25_migrations)C++20
22.09 / 100
38 ms1436 KiB
#include <bits/stdc++.h>
using namespace std;

// ----- global data (kept between calls of send_message) -----
static int N_global = 0;            // number of sites
static int LOG_ = 0;                // bit length of N
static vector<int> depth_;          // depth of each node
static vector<vector<int>> up_;     // up_[node][k] = 2^k ancestor
static vector<int> parent_;         // parent[node]
static int diam_u = 0;              // one endpoint of current diameter
static int diam_v = 0;              // the other endpoint
static int diam_len = 0;            // length of current diameter
static int sent_at_n2 = -1;         // value sent at site N-2 (a+1)
static vector<int> S_global;        // list of messages

static int lca_(int u, int v) {
    if (depth_[u] < depth_[v]) swap(u, v);
    int diff = depth_[u] - depth_[v];
    for (int k = LOG_ - 1; k >= 0; --k) {
        if (diff & (1 << k)) {
            u = up_[u][k];
        }
    }
    if (u == v) return u;
    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];
}

static int distance_(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 on the first call
    if (N_global == 0) {
        N_global = N;
        LOG_ = 0;
        while ((1 << LOG_) <= N) ++LOG_;
        ++LOG_; // a bit more than needed

        depth_.assign(N, 0);
        up_.assign(N, vector<int>(LOG_, -1));
        parent_.assign(N, -1);
        S_global.assign(N, 0);
        diam_u = diam_v = 0;
        diam_len = 0;
        sent_at_n2 = -1;
    }

    // store the edge i - Pi
    parent_[i] = Pi;
    depth_[i] = depth_[Pi] + 1;
    up_[i][0] = Pi;
    for (int k = 1; k < LOG_; ++k) {
        int prev = up_[i][k - 1];
        up_[i][k] = (prev != -1 ? up_[prev][k - 1] : -1);
    }

    // ----- compute distances to current diameter endpoints -----
    int d_i_u = distance_(i, diam_u);
    int d_i_v = distance_(i, diam_v);

    // candidate new diameter
    int new_u = diam_u, new_v = diam_v, new_len = diam_len;
    if (d_i_u > new_len && d_i_u >= d_i_v) {
        new_u = diam_u;
        new_v = i;
        new_len = d_i_u;
    } else if (d_i_v > new_len && d_i_v > d_i_u) {
        new_u = i;
        new_v = diam_v;
        new_len = d_i_v;
    }

    // ----- site N-2 : store the smaller endpoint of the current diameter -----
    if (i == N - 2) {
        int a = min(new_u, new_v);
        int val = a + 1; // 1 ... 10000
        S_global[i] = val;
        sent_at_n2 = val;

        diam_u = new_u;
        diam_v = new_v;
        diam_len = new_len;
        return val;
    }

    // ----- site N-1 : send the final information -----
    if (i == N - 1) {
        int a = min(diam_u, diam_v);
        int b = max(diam_u, diam_v);
        int cur_len = diam_len; // distance(a,b)

        int d_i_a = distance_(i, a);
        int d_i_b = distance_(i, b);

        int leaf_val = N; // leaf index is N-1, leaf_val = leaf+1 = N
        int val2;
        if (d_i_a <= cur_len && d_i_b <= cur_len) {
            // unchanged diameter
            val2 = b + 1; // <= N-1
        } else {
            // leaf gives a longer diameter
            if (d_i_a > cur_len && d_i_a >= d_i_b) {
                // new diameter (a, leaf)
                val2 = leaf_val; // = N
            } else {
                // new diameter (b, leaf)
                val2 = leaf_val + (b - a); // <= 19998
            }
        }
        S_global[i] = val2;

        diam_u = new_u;
        diam_v = new_v;
        diam_len = new_len;
        return val2;
    }

    // all other sites: no message
    S_global[i] = 0;
    diam_u = new_u;
    diam_v = new_v;
    diam_len = new_len;
    return 0;
}

std::pair<int, int> longest_path(std::vector<int> S) {
    int N = (int)S.size();
    int leaf_val = N; // leaf index is N-1, stored as leaf+1 = N

    // find non-zero entries
    vector<pair<int, int>> nz;
    for (int idx = 0; idx < N; ++idx) {
        if (S[idx] != 0) nz.push_back({idx, S[idx]});
    }

    if ((int)nz.size() < 2) {
        // fallback
        return {0, 0};
    }

    sort(nz.begin(), nz.end());

    // the two largest indices are nz[-2] and nz[-1]
    auto [i1, val1] = nz[(int)nz.size() - 2];
    auto [i2, val2] = nz[(int)nz.size() - 1];
    (void)i1;
    (void)i2;

    int a = val1 - 1; // stored a (the smaller endpoint after N-2)

    int U, V;
    if (val2 == leaf_val) {
        U = a;
        V = N - 1;
    } else if (val2 > leaf_val) {
        // leaf case with the larger original endpoint
        U = a + (val2 - leaf_val);
        V = N - 1;
    } else {
        // unchanged case
        U = a;
        V = val2 - 1;
    }

    if (U > V) swap(U, V);
    return {U, V};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...