제출 #1342597

#제출 시각아이디문제언어결과실행 시간메모리
1342597mehrzad이주 (IOI25_migrations)C++17
16 / 100
30 ms1056 KiB

#include "migrations.h"
#include <vector>
#include <algorithm>
using namespace std;

const int N_MAX = 10000;
const int LOG = 14; // 2^14 = 16384 > 10000

static vector<vector<int>> up(LOG, vector<int>(N_MAX, -1));
static vector<int> depth(N_MAX, 0);
static int A = 0, B = 0;               // current diameter endpoints
static int msg_sent = 0;               // number of messages sent so far (not needed)
const int KEEP_A = 1, KEEP_B = 2;      // codes for update

int send_message(int N, int i, int Pi) {
    // add node i with parent Pi
    up[0][i] = Pi;
    depth[i] = depth[Pi] + 1;
    for (int k = 1; k < LOG; ++k) {
        int mid = up[k-1][i];
        up[k][i] = (mid == -1) ? -1 : up[k-1][mid];
    }

    // compute distances to current endpoints
    auto dist = [&](int u, int v) -> int {
        if (u == v) return 0;
        int du = depth[u], dv = depth[v];
        // lift deeper node
        if (du < dv) {
            for (int k = LOG-1; k >= 0; --k)
                if (dv - (1<<k) >= du && up[k][v] != -1)
                    v = up[k][v];
            swap(u, v);
        } else if (du > dv) {
            for (int k = LOG-1; k >= 0; --k)
                if (du - (1<<k) >= dv && up[k][u] != -1)
                    u = up[k][u];
        }
        // now same depth
        for (int k = LOG-1; k >= 0; --k)
            if (up[k][u] != -1 && up[k][u] != -1 && up[k][u] == up[k][v])
                u = up[k][u], v = up[k][v];
        if (u == v) return depth[i] + depth[i]; // actually distance is du + dv - 2*depth[lca]
        return depth[i] + depth[i] - 2*depth[u];
    };
    // But we only need distances from i to A and B, and from A to B.
    // We can recompute quickly:
    auto lca = [&](int u, int v) {
        if (depth[u] < depth[v]) swap(u, v);
        for (int k = LOG-1; k >= 0; --k)
            if (depth[u] - (1<<k) >= depth[v] && up[k][u] != -1)
                u = up[k][u];
        if (u == v) return u;
        for (int k = LOG-1; k >= 0; --k)
            if (up[k][u] != -1 && up[k][u] != up[k][v])
                u = up[k][u], v = up[k][v];
        return up[0][u];
    };
    int dA = depth[i] + depth[A] - 2*depth[lca(i, A)];
    int dB = depth[i] + depth[B] - 2*depth[lca(i, B)];
    int oldDiam = depth[A] + depth[B] - 2*depth[lca(A, B)];

    // Determine if diameter increases and which endpoint stays
    int code = 0; // no change
    if (max(dA, dB) > oldDiam) {
        if (dA >= dB) {
            code = KEEP_A;   // B becomes i
        } else {
            code = KEEP_B;   // A becomes i
        }
    }

    // Decision for messages: we will use the last 50 nodes.
    const int START = N - 50;  // 9950 for N=10000
    int msg = 0;

    if (i >= START) {
        if (i == START) {
            // send A before any changes in this segment
            msg = A;
        } else if (i == START+1) {
            // send B before any changes in this segment
            msg = B;
        } else {
            // send the code for this node
            msg = code;  // 0,1,2
        }
    }
    // Apply the update to (A,B) if code != 0
    if (code == KEEP_A) {
        B = i;
    } else if (code == KEEP_B) {
        A = i;
    }
    // else keep unchanged

    return msg;
}

pair<int, int> longest_path(vector<int> S) {
    int N = S.size();
    const int START = N - 50;
    int A = S[START];
    int B = S[START+1];
    // process the remaining nodes
    for (int i = START+2; i < N; ++i) {
        int code = S[i];
        if (code == 0) {
            // no change, nothing to do
        } else if (code == 1) {
            B = i;
        } else { // code == 2
            A = i;
        }
    }
    return {A, B};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...