Cod sursa(job #1653145)

Utilizator BrandonChris Luntraru Brandon Data 15 martie 2016 19:12:04
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.06 kb
/*#include <cstdio>
#include <cmath>
#include <vector>

using namespace std;

vector <int> G[100005];

int n, q, ancestor[20][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;
}*/
#include <fstream>
#include <cmath>
#include <vector>

using namespace std;

ifstream cin("lca.in");
ofstream cout("lca.out");

vector <int> G[100005], euler, lvl;

int pos[100005], n, q, rmq[20][100005];
bool used[100005];

void euler_init(int node, int level) {
    used[node] = true;
    euler.push_back(node);
    lvl.push_back(level);
    pos[node] = euler.size() - 1;

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

        euler_init(it, level + 1);
        euler.push_back(node);
        lvl.push_back(level);
    }
}

void rmq_init() {
    for(int i = 1; i <= (int) lvl.size(); ++i) {
        rmq[0][i] = i;
    }

    for(int i = 1; (1 << i) <= (int) lvl.size(); ++i) {
        for(int j = 1; j + (1 << i) <= (int) lvl.size(); ++j) {
            //rmq[i][j] = min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
            if(lvl[rmq[i - 1][j] - 1] <= lvl[rmq[i - 1][j + (1 << (i - 1))] - 1]) {
                rmq[i][j] = rmq[i - 1][j];
            }
            else {
                rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
            }
        }
    }
}

int query(int lft, int rgt) {
    int line, skip, rmq_ans;
    skip = rgt - lft + 1;
    line = log2(skip);

    if(lvl[rmq[line][lft] - 1] <= lvl[rmq[line][lft + skip - (1 << line)] - 1]) {
        rmq_ans = rmq[line][lft];
    }
    else {
        rmq_ans = rmq[line][lft + skip - (1 << line)];
    }

    return euler[rmq_ans - 1];
}

int main() {
    cin >> n >> q;

    for(int i = 2; i <= n; ++i) {
        int x;
        cin >> x;
        G[x].push_back(i);
        G[i].push_back(x);
    }

    euler_init(1, 0);
    rmq_init();

    /*for(int i = 0; i <= log2(lvl.size()); ++i) {
        for(int j = 1; j <= lvl.size(); ++j) {
            cout << rmq[i][j] << ' ';
        }

        cout << '\n';
    }*/

    for(int i = 1; i <= q; ++i) {
        int node1, node2;
        cin >> node1 >> node2;

        if(pos[node1] > pos[node2]) {
            swap(node1, node2);
        }

        cout << query(pos[node1] + 1, pos[node2] + 1) << '\n';
        ///+1 because of lvl and euler start from 0 and so does pos, but rmq starts from 1
    }

    return 0;
}