Cod sursa(job #2492064)

Utilizator MatteoalexandruMatteo Verzotti Matteoalexandru Data 13 noiembrie 2019 21:34:55
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.57 kb
/*
                `-/oo+/-   ``
              .oyhhhhhhyo.`od
             +hhhhyyoooos. h/
            +hhyso++oosy- /s
           .yoooossyyo:``-y`
            ..----.` ``.-/+:.`
                   `````..-::/.
                  `..```.-::///`
                 `-.....--::::/:
                `.......--::////:
               `...`....---:::://:
             `......``..--:::::///:`
            `---.......--:::::////+/`
            ----------::::::/::///++:
            ----:---:::::///////////:`
            .----::::::////////////:-`
            `----::::::::::/::::::::-
             `.-----:::::::::::::::-
               ...----:::::::::/:-`
                 `.---::/+osss+:`
                   ``.:://///-.
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <cmath>

using namespace std;

const int INF = 2e9;
const int N = 1e5;
const int LOG = 20;

vector <int> G[5 + N];
int tour[5 + 2 * N];
int lg[LOG];
int rmq[LOG][5 + 2 * N];
int L[5 + 2 * N];
int first[5 + 2 * N];

int n, m, k;

void build_tour(int node, int lev) {
    tour[++k] = node;
    L[k] = lev;
    first[node] = k;

    for(auto it : G[node]) {
        build_tour(it, lev + 1);
        tour[++k] = node;
        L[k] = lev;
    }
}

void compute_rmq() {

    for(int i = 2; i <= k; i++) lg[i] = 1 + lg[i >> 1];
    for(int i = 1; i <= k; i++) rmq[0][i] = i;

    for(int i = 1; i <= lg[k]; i++) {

        for(int j = 1; j + (1 << i) <= k + 1; j++) {
            rmq[i][j] = rmq[i - 1][j];

            if(L[rmq[i - 1][j + (1 << (i - 1))]] < L[rmq[i][j]])
                rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
        }
    }
}

int compute_lca(int x, int y) {
    int a, b, dif, l, sol;
    a = first[x];
    b = first[y];
    if(a > b) a ^= b ^= a ^= b;
    dif = b - a + 1;
    l = lg[dif];
    sol = rmq[l][a];
    dif = dif - (1 << l);
    if(L[sol] > L[rmq[l][a + dif]]) sol = rmq[l][a + dif];
    return tour[sol];
}

int main() {
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i = 2; i <= n; i++) {
        int x;
        scanf("%d", &x);
        G[x].push_back(i);
    }
    L[1] = 1;
    build_tour(1, 0);
    compute_rmq();
    //for(int i = 1; i < 2 * n; i++) printf("%d ", tour[i]);

    while(m--) {
        int x, y, i;
        scanf("%d%d", &x, &y);
        printf("%d\n", compute_lca(x, y));
    }
    return 0;
}