Cod sursa(job #1723561)

Utilizator oldatlantianSerban Cercelescu oldatlantian Data 30 iunie 2016 22:19:58
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.47 kb
#include <bits/stdc++.h>
using namespace std;

const int NMAX = 100005,
          MMAX = 200005;

vector<int> g[NMAX];
int   buff;
int   rmq[20][NMAX],
            f[NMAX],
            h[NMAX],
            l[MMAX],
           lg[MMAX];

void dfs(int u, int th) {
    l[++buff] = u;
    h[u]      = th;
    f[u]      = buff;
    for(auto i:g[u]) {
        dfs(i, th+1);
        l[++buff] = u;
    }
}

void build_rmq(void) {
    for(int i=2; i<=buff; ++i)
        lg[i] = lg[i-1] + int((i&i-1)==0);

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

    for(int i=1; i<=lg[buff]; ++i) {
    for(int j=1; j<=buff; ++j) {
        rmq[i][j] = rmq[i-1][j];
        if(j+(1<<i-1)<=buff && h[rmq[i-1][j+(1<<i-1)]]<h[rmq[i][j]])
            rmq[i][j] = rmq[i-1][j+(1<<i-1)];
    }}
}

int lca(int a, int b) {
    a = f[a];
    b = f[b];
    if(a>b)
        swap(a, b);
    if(h[rmq[lg[b-a+1]][a]] < h[rmq[lg[b-a+1]][b-(1<<lg[b-a+1])+1]])
        return rmq[lg[b-a+1]][a];
    else
        return rmq[lg[b-a+1]][b-(1<<lg[b-a+1])+1];
}

int main(void) {
    freopen("lca.in",  "r", stdin);
    freopen("lca.out", "w", stdout);
    int n, m, a, b;

    scanf("%d%d",&n,&m);
    for(int i=2; i<=n; ++i) {
        scanf("%d",&a);
        g[a].push_back(i);
    }

    dfs(1, 1);
    build_rmq();

    while(m--) {
        scanf("%d%d",&a,&b);
        printf("%d\n",lca(a, b));
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}