Cod sursa(job #2350417)

Utilizator MarianConstantinMarian Constantin MarianConstantin Data 21 februarie 2019 12:36:02
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.59 kb
#include <iostream>
#include <fstream>
#include <vector>
#define pb push_back

using namespace std;

const int MAXN = 100010, MAXL = 20;
bool visited[MAXN];
int euler[MAXN << 1], depths[MAXN << 1], first[MAXN], rmq[MAXL][MAXN << 2], log[MAXN << 1], q, nr, n;
vector<int> sons[MAXN];
ifstream fin("lca.in");
ofstream fout("lca.out");

void generateEuler(int vertix, int depth) {
    visited[vertix] = true;
    depths[nr] = depth;
    first[vertix] = nr;
    euler[nr++] = vertix;
    for (auto &it: sons[vertix]) {
        if (visited[it] == false) {
            generateEuler(it, depth + 1);
            depths[nr] = depth;
            euler[nr++] = vertix;
        }
    }
}

int doMin(int a, int b) {
    if (depths[a] < depths[b])
        return a;
    return b;
}

void preprocess() {
    for (int i = 2; i <= nr; i++)
        log[i] = log[i >> 1] + 1;
    for (int j = 0; j < nr; j++)
        rmq[0][j] = j;
    for (int i = 1; (1 << i) <= nr; i++) {
        for (int j = 0; j + (1 << i) - 1 < nr; j++) {
            rmq[i][j] = doMin(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
        }
    }
}

int doRmq(int l, int r) {
    if (l > r)
        swap(l, r);
    int k = log[r - l + 1];
    return doMin(rmq[k][l], rmq[k][r - (1 << k) + 1]);
}

int main() {
    int x, y;
    fin >> n >> q;
    for (int i = 2; i <= n; ++i) {
        fin >> x;
        sons[x].pb(i);
    }
    generateEuler(1, 0);
    preprocess();
    for (int i = 1; i <= q; ++i) {
        fin >> x >> y;
        fout << euler[doRmq(first[x], first[y])] << "\n";
    }
    return 0;
}