Submission #1274810

#TimeUsernameProblemLanguageResultExecution timeMemory
1274810mehrzadMigrations (IOI25_migrations)C++17
22.09 / 100
33 ms912 KiB
#include "migrations.h"
#include <bits/stdc++.h>
using namespace std;

static bool initialized = false;
static int N_global = 0;
static const int LOGV = 15;                 // 2^14 = 16384 > 10000
static vector<int> parentArr;
static vector<int> depthArr;
static vector<array<int, LOGV>> upArr;

static int endA = 0, endB = 0, curDist = 0; // current diameter endpoints and length
static int repl_Nminus2 = -1;               // replacement code for node N-2 (0/1/2)

static int lca(int u, int v) {
    if (depthArr[u] < depthArr[v]) swap(u, v);
    int diff = depthArr[u] - depthArr[v];
    for (int k = 0; diff; ++k) {
        if (diff & 1) u = upArr[u][k];
        diff >>= 1;
    }
    if (u == v) return u;
    for (int k = LOGV - 1; k >= 0; --k) {
        if (upArr[u][k] != upArr[v][k]) {
            u = upArr[u][k];
            v = upArr[v][k];
        }
    }
    return upArr[u][0];
}
static int dist(int u, int v) {
    int w = lca(u, v);
    return depthArr[u] + depthArr[v] - 2 * depthArr[w];
}

/*  return code of what happened when node x is added:
    0 – no change,
    1 – endpoint A is replaced by x,
    2 – endpoint B is replaced by x   */
static int update_diameter(int x) {
    int da = dist(x, endA);
    int db = dist(x, endB);
    if (da > curDist) {
        endB = x;
        curDist = da;
        return 2;
    } else if (db > curDist) {
        endA = x;
        curDist = db;
        return 1;
    }
    return 0;
}

int send_message(int N, int i, int Pi) {
    if (!initialized) {
        N_global = N;
        parentArr.assign(N, -1);
        depthArr.assign(N, 0);
        upArr.assign(N, array<int, LOGV>{});
        for (int k = 0; k < LOGV; ++k) upArr[0][k] = 0;   // root
        endA = endB = 0;
        curDist = 0;
        repl_Nminus2 = -1;
        initialized = true;
    }

    // add node i
    parentArr[i] = Pi;
    depthArr[i] = depthArr[Pi] + 1;
    upArr[i][0] = Pi;
    for (int k = 1; k < LOGV; ++k)
        upArr[i][k] = upArr[ upArr[i][k - 1] ][k - 1];

    // handle tiny N specially
    if (N_global == 2) {
        update_diameter(i);
        return 0;
    }
    if (N_global == 3) {
        if (i == 1) {
            update_diameter(i);
            return 0;
        } else { // i == 2, last node
            update_diameter(i);
            int a = endA, b = endB;
            if (a > b) swap(a, b);
            int code = a * N_global + b + 1; // fits into [1,9] for N=3
            return code;
        }
    }

    // general case N >= 4
    if (i == N_global - 3) {
        // after processing this node, send endpoint A
        update_diameter(i);
        return endA + 1;
    }
    if (i == N_global - 2) {
        // store current endpoint B before possible change
        int storedB = endB;
        repl_Nminus2 = update_diameter(i);
        return storedB + 1;
    }
    if (i == N_global - 1) {
        int repl_last = update_diameter(i);
        int code = repl_Nminus2 * 3 + repl_last; // 0..8
        return code + 1;                         // 1..9
    }
    // all other nodes
    update_diameter(i);
    return 0;
}

std::pair<int, int> longest_path(std::vector<int> S) {
    int N = (int)S.size();
    if (N == 2) return {0, 1};
    if (N == 3) {
        int code = -1;
        for (int i = 0; i < N; ++i) if (S[i] != 0) { code = S[i] - 1; break; }
        int a = code / N;
        int b = code % N;
        return {a, b};
    }
    // N >= 4
    int a = S[N - 3] - 1;
    int b = S[N - 2] - 1;
    int code = S[N - 1] - 1;
    int r2 = code / 3;
    int r3 = code % 3;
    if (r2 == 1) a = N - 2;
    else if (r2 == 2) b = N - 2;
    if (r3 == 1) a = N - 1;
    else if (r3 == 2) b = N - 1;
    return {a, b};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...