Cod sursa(job #2467921)

Utilizator sichetpaulSichet Paul sichetpaul Data 5 octombrie 2019 10:47:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.43 kb
#include <bits/stdc++.h>
#define Nmax 100001
using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

int N, M, K;
int E[5 * Nmax], lev[5 * Nmax], pos[Nmax], lg[5 * Nmax], rmq[5 * Nmax][20];
vector<int> G[Nmax];
void update(int node, int father) {
   ++K;
   E[K] = node;
   lev[K] = lev[pos[father]] + 1;
   if (!pos[node]) pos[node] = K;
}

void DFS(int node, int father) {
    update(node, father);
    for (auto it: G[node]) {
        DFS(it, node);
        update(node, father);
    }
}
void RMQ() {
    for (int i = 2; i <= K; ++i)
        lg[i] = lg[i / 2] + 1;

    for (int i = 1; i <= K; ++i)
        rmq[i][0] = i;

    for (int j = 1; (1 << j) <= K; ++j)
    for (int i = 1; i + (1 << j) - 1 <= K; ++i) {
        int x = rmq[i][j - 1], y = rmq[i + (1 << (j - 1))][j - 1];
        if (lev[x] < lev[y]) rmq[i][j] = x;
        else rmq[i][j] = y;
    }
}
int solve_query(int le, int ri) {
    int mid = lg[ri - le + 1];
    int a = rmq[le][mid], b = rmq[ri - (1 << mid) + 1][mid];
    if (lev[a] < lev[b]) return E[a];
    return E[b];
}
int main()
{
    f >> N >> M;
    for (int i = 2; i <= N; ++i) {
        int x;
        f >> x;
        G[x].push_back(i);
    }

    DFS(1,0);
    RMQ();

    for (int i = 1; i <= M; ++i) {
        int x, y;
        f >> x >> y;
        if (pos[x] > pos[y]) swap(x, y);
        g << solve_query(pos[x], pos[y]) << '\n';
    }

    return 0;
}