Cod sursa(job #1998476)

Utilizator savigunFeleaga Dragos-George savigun Data 8 iulie 2017 00:09:44
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.93 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

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

const int MAXN = 1e5 + 5;
int n, m;
int depth[MAXN], parent[MAXN], pos[MAXN], log[2 * MAXN], ePath[2 * MAXN], eSize;
pair<int, int>* dp[20];
vector<int> g[MAXN];


void set_log() {
    int next = 2;
    int lg = 0;
    for (int i = 1; i < 2 * MAXN; ++i) {
        if (i == next) {
            lg++;
            next *= 2;
        }
        log[i] = lg;
    }
}

void set_level(int x, int lvl) {
    depth[x] = lvl;
    for (int i = 0; i < g[x].size(); ++i) {
        int y = g[x][i];
        if (y != parent[x]) set_level(y, lvl + 1);
    }
}

void euler_dfs(int x) {
    pos[x] = eSize;
    ePath[eSize++] = x;

    for (int i = 0; i < g[x].size(); ++i) {
        int y = g[x][i];
        if (y != parent[x]) {
            euler_dfs(y);
            ePath[eSize++] = x;
        }
    }
}

void rmq() {
    for (int i = 0; i <= log[eSize]; ++i) dp[i] = new pair<int, int>[eSize];
    for (int i = 0; i < eSize; ++i) dp[0][i] = {depth[ePath[i]], ePath[i]};

    for (int k = 1; k <= log[eSize]; ++k) {
        int mid = 1 << (k - 1);
        for (int i = 0; i < eSize - mid; ++i) {
            dp[k][i] = min(dp[k-1][i], dp[k - 1][i + mid]);
        }
    }
}

int query(int x, int y) {
    int length = pos[y] - pos[x] + 1;
    int lg = log[length];
    int dif = length - (1 << lg);
    return min(dp[lg][pos[x]], dp[lg][pos[x] + dif]).second;
}


int main()
{
    in >> n >> m;
    for (int i = 2, x; i <= n; ++i) {
        in >> x;
        parent[i] = x;
        g[i].push_back(x);
        g[x].push_back(i);
    }

    set_level(1, 1);

    euler_dfs(1);

    set_log();

    rmq();

    for (int i = 1, x, y; i <= m; ++i) {
        in >> x >> y;
        if (pos[x] > pos[y]) swap(x, y);
        out << query(x, y) << "\n";
    }

    return 0;
}