Cod sursa(job #2170547)

Utilizator LittleWhoFeraru Mihail LittleWho Data 15 martie 2018 08:04:30
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.67 kb
#include <bits/stdc++.h>

using namespace std;

const int nmax = static_cast<int> (2 * (1e5+1));
const int lgnmax = 19;

int n, m;
int dp[lgnmax][nmax];

inline int pow2(int x) {
    return (1 << x);
}

int lg2[nmax];
void precalc_lg2() {
    lg2[0] = 1;
    for (int i = 2; i <= n; i++) {
        lg2[i] = lg2[i / 2] + 1;
    }
}

vector<int> graph[nmax];
int level[nmax];
int first[nmax];
int euler_cnt;

void euler_df(int node, int clevel) {
    level[node] = clevel;
    dp[0][++euler_cnt] = node;
    first[node] = euler_cnt;

    for (auto &next_node: graph[node]) {
        euler_df(next_node, clevel + 1);
        dp[0][++euler_cnt] = node;
    }
}

void build_rmq() {
    precalc_lg2();

    for (int i = 1; i <= lg2[n]; i++) {
        for (int j = 1; j <= n - pow2(i) + 1; j++) {
            if (level[dp[i - 1][j]] < level[dp[i - 1][j + pow2(i - 1)]]) {
                dp[i][j] = dp[i - 1][j];
            } else {
                dp[i][j] = dp[i - 1][j + pow2(i - 1)];
            }
        }
    }
}

int query(int x, int y) {
    x = first[x];
    y = first[y];

    if (x > y) swap(x, y);
    int k = lg2[y - x + 1];

    if (level[dp[k][x]] < level[dp[k][y - pow2(k) + 1]]) {
        return dp[k][x];
    }
    return dp[k][y - pow2(k) + 1];
}

int main() {
    freopen("carici.in", "r", stdin);

    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    scanf("%d%d", &n, &m);
    for (int i = 1, x; i < n; i++) {
        scanf("%d", &x);
        graph[x].push_back(i + 1);
    }

    euler_df(1, 0);
    n = euler_cnt;
    build_rmq();

    for (int i = 0, x, y; i < m; i++) {
        scanf("%d%d", &x, &y);
        cout << query(x, y) << "\n";
    }

    return 0;
}