Cod sursa(job #2604861)

Utilizator copanelTudor Roman copanel Data 23 aprilie 2020 17:43:03
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.1 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

struct node {
    std::vector<int> children;
    int parent;
    int first_euler;
    int level;
} nodes[100001];
int euler[200002];
int rmq[17][100001];
int log2[200002];

void dfs_euler(int node) {
    static int euler_i;

    euler[++euler_i] = node;
    nodes[node].first_euler = euler_i;
    for (const int child_id : nodes[node].children) {
        auto& child = nodes[child_id];
        if (child.first_euler == 0) {
            child.level = nodes[node].level + 1;
            dfs_euler(child_id);
            euler[++euler_i] = node;
        }
    }
}

int lca(int n, int a, int b) {
    int p = nodes[a].first_euler, q = nodes[b].first_euler;
    if (p > q) {
        std::swap(p, q);
    }
    int l = log2[q - p + 1];
    int st = rmq[l][p + (1 << l) - 1];
    int dr = rmq[l][q];
    if (nodes[st].level < nodes[dr].level) {
        return st;
    } else {
        return dr;
    }
}

void compute_log2(int n) {
    log2[1] = 0;
    for (int i = 2; i <= 2 * n - 1; i++) {
        log2[i] = log2[i / 2] + 1;
    }
}

int main() {
    std::ifstream fin("lca.in");
    std::ofstream fout("lca.out");
    int n, m;

    fin >> n >> m;
    nodes[1].level = 0;
    for (int i = 2; i <= n; i++) {
        fin >> nodes[i].parent;
        nodes[nodes[i].parent].children.push_back(i);
    }

    dfs_euler(1);
    compute_log2(n);

    // Pentru fiecare nod din parcurgerea Euler stim nivelul la care se afla.
    // Calculam matricea RMQ pentru nivelul minim intr-un interval din parcurgerea Euler.
    for (int j = 1; j <= 2 * n - 1; j++) {
        rmq[0][j] = euler[j];
    }
    for (int i = 1; (1 << i) <= 2 * n - 1; i++) {
        for (int j = 1; j <= 2 * n - 1; j++) {
            int st = rmq[i - 1][j - (1 << (i - 1))];
            int dr = rmq[i - 1][j];
            if (nodes[st].level < nodes[dr].level) {
                rmq[i][j] = st;
            } else {
                rmq[i][j] = dr;
            }
        }
    }

    for (int i = 0; i < m; i++) {
        int a, b;
        fin >> a >> b;
        fout << lca(n, a, b) << '\n';
    }
    return 0;
}