제출 #1343075

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

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

const int MAXN = 10000;
const int LOG = 14; // 2^14 > 10000
const int K = 2500; // bucket size for ranking

static int N_global;
static int parent[MAXN];
static int depth[MAXN];
static int up[MAXN][LOG];
static int cur_a, cur_b;
static int stored_idx; // remainder for last step
static bool inited = false;

// ----- LCA and distance -----
int lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    int diff = depth[u] - depth[v];
    for (int k = 0; k < LOG; ++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];
}

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) {
    if (!inited) {
        N_global = N;
        depth[0] = 0;
        for (int k = 0; k < LOG; ++k) up[0][k] = 0;
        cur_a = cur_b = 0;
        inited = true;
    }

    // add node i
    parent[i] = Pi;
    depth[i] = depth[Pi] + 1;
    up[i][0] = Pi;
    for (int k = 1; k < LOG; ++k)
        up[i][k] = up[ up[i][k-1] ][k-1];

    if (i == N - 2) {
        // update diameter with node i
        int d_ab = dist(cur_a, cur_b);
        int d_ai = dist(cur_a, i);
        int d_bi = dist(cur_b, i);
        int maxd = d_ab;
        int new_a = cur_a, new_b = cur_b;
        if (d_ai > maxd) { maxd = d_ai; new_a = cur_a; new_b = i; }
        if (d_bi > maxd) { maxd = d_bi; new_a = i; new_b = cur_b; }
        cur_a = new_a; cur_b = new_b;

        // encode the pair (cur_a, cur_b)
        int n = N - 1;  // number of nodes before the last one
        int lo = min(cur_a, cur_b), hi = max(cur_a, cur_b);
        long long rank = lo * (2LL * n - lo - 1) / 2 + (hi - lo - 1);
        stored_idx = rank % K;
        int bucket = rank / K;
        return bucket + 1;   // 1 … 20000
    }
    else if (i == N - 1) {
        // use the old diameter (cur_a, cur_b) to decide the final pair
        int d_ab = dist(cur_a, cur_b);
        int d_ai = dist(cur_a, i);
        int d_bi = dist(cur_b, i);
        int choice = 0; // 0 -> (cur_a,cur_b), 1 -> (cur_a,i), 2 -> (cur_b,i)
        if (d_ai > d_ab) choice = 1;
        else if (d_bi > d_ab) choice = 2;
        int v2 = stored_idx * 3 + choice + 1;
        return v2;
    }
    else {
        // ordinary update for earlier nodes
        int d_ab = dist(cur_a, cur_b);
        int d_ai = dist(cur_a, i);
        int d_bi = dist(cur_b, i);
        int maxd = d_ab;
        int new_a = cur_a, new_b = cur_b;
        if (d_ai > maxd) { maxd = d_ai; new_a = cur_a; new_b = i; }
        if (d_bi > maxd) { maxd = d_bi; new_a = i; new_b = cur_b; }
        cur_a = new_a; cur_b = new_b;
        return 0;   // no message
    }
}

pair<int, int> longest_path(vector<int> S) {
    int N = S.size();
    int v1 = S[N-2];
    int v2 = S[N-1];

    int bucket = v1 - 1;
    int t = v2 - 1;
    int idx = t / 3;
    int choice = t % 3;

    int n = N - 1;   // number of nodes before last
    long long rank = bucket * K + idx;

    // find the unordered pair (lo,hi) from rank
    int lo = -1, hi = -1;
    for (int x = 0; x < n; ++x) {
        long long start = x * (2LL * n - x - 1) / 2;
        long long cnt = n - x - 1;
        if (rank >= start && rank < start + cnt) {
            lo = x;
            hi = x + 1 + (rank - start);
            break;
        }
    }

    if (choice == 0)
        return {lo, hi};
    else if (choice == 1)
        return {lo, N-1};
    else // choice == 2
        return {hi, N-1};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...