Cod sursa(job #1556312)

Utilizator andreiiiiPopa Andrei andreiiii Data 24 decembrie 2015 16:18:18
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.68 kb
#include <algorithm>
#include <cstring>
#include <fstream>
using namespace std;

const int NMAX = 100005;

vector<int> G[NMAX];
int father[NMAX], level[NMAX];

int euler[2 * NMAX], first[NMAX], last[NMAX], euLevel[2 * NMAX], eu;
int rmq[20][2 * NMAX], plog[2 * NMAX];

void dfs(int node, int prev) {
    level[node] = level[prev] + 1;

    euler[++eu] = node;
    euLevel[eu] = level[node];
    first[node] = eu;
    for (int p: G[node]) {
        dfs(p, node);
        euler[++eu] = node;
        euLevel[eu] = level[node];
    }

    last[node] = eu;
}

void buildRMQ() {
    for (int i = 2; i <= eu; ++i) {
        plog[i] = plog[i / 2] + 1;
    }
    for (int i = 1; i <= eu; ++i)
        rmq[0][i] = i;
    for (int k = 1; (1 << k) <= eu; ++k) {
        int y = 1 << k - 1;
        for (int i = 1; i + (1 << k) - 1 <= eu; ++i) {
            rmq[k][i] = rmq[k - 1][i];
            if (euLevel[rmq[k - 1][i + y]] < euLevel[rmq[k][i]]) {
                rmq[k][i] = rmq[k - 1][i + y];
            }
        }
    }
}

int lca(int x, int y) {
    x = first[x];
    y = first[y];
    if (x > y) swap(x, y);
    
    int diff = plog[y - x + 1];
    int ret = rmq[diff][x];
    if (euLevel[rmq[diff][y - (1 << diff) + 1]] < euLevel[ret]) {
        ret = rmq[diff][y - (1 << diff) + 1];
    }
    return euler[ret];
}

int main() {
    ifstream fin("lca.in");
    ofstream fout("lca.out");

    int n, q;
    fin >> n >> q;

    for (int i = 2; i <= n; ++i) {
        int x;
        fin >> x;
        G[x].push_back(i);
        father[i] = x;
    }
    dfs(1, 0);
    buildRMQ();

    while (q-- > 0) {
        int x, y;
        fin >> x >> y;
        fout << lca(x, y) << '\n';
    }

    fin.close();
    fout.close();
}