Cod sursa(job #1639409)

Utilizator BrandonChris Luntraru Brandon Data 8 martie 2016 12:13:33
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.84 kb
#include <fstream>
#include <cmath>
#include <vector>

using namespace std;

vector <int> G[10005];

int n, q, ancestor[18][100005], depth[100005], log_n;
bool used[100005];

void dfs(int node, int step) {
    used[node] = true;

    for(auto nxt: G[node]) {
        if(used[nxt]) {
            continue;
        }

        dfs(nxt, step + 1);
        depth[nxt] = step;
    }
}

inline void ancestor_init() {
    log_n = log2(n) + 1;

    for(int i = 1; i <= log_n; ++i) {
        for(int j = 1; j <= n; ++j) {
            ancestor[i][j] = ancestor[i - 1][ancestor[i - 1][j]];
        }
    }
}

inline void equalise(int &node_deep, int &node_norm) {
    if(depth[node_deep] < depth[node_norm]) {
        swap(node_deep, node_norm);
    }

    int dist = depth[node_deep] - depth[node_norm];

    for(int j = 0; j <= log_n; ++j) {
        int bitmask = (1 << j);

        if(dist & bitmask) {
            node_deep = ancestor[j][node_deep];
        }
    }
}

inline int lca(int node1, int node2) {
    if(node1 == node2) {
        return node1;
    }

    for(int j = log_n; j >= 0; --j) {
        if(ancestor[j][node1] != ancestor[j][node2] and ancestor[j][node1]) {
            node1 = ancestor[j][node1];
            node2 = ancestor[j][node2];
        }
    }

    return ancestor[0][node1];
}

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

    scanf("%d%d", &n, &q);
    ancestor[0][1] = 1;

    for(int i = 2; i <= n; ++i) {
        scanf("%d", &ancestor[0][i]);
        G[ancestor[0][i]].push_back(i);
    }

    dfs(1, 0);
    ancestor_init();

    for(int i = 1; i <= q; ++i) {
        int node1, node2;
        scanf("%d%d", &node1, &node2);
        equalise(node1, node2);
        printf("%d\n", lca(node1, node2));
    }

    return 0;
}