Cod sursa(job #974231)

Utilizator CosminRusuCosmin Rusu CosminRusu Data 16 iulie 2013 17:39:43
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.87 kb
/*
    First of all : The <b><u>RMQ</u></b> version !!
*/
#include <fstream>
#include <vector>
#include <bitset>
#include <queue>
#include <algorithm>
#include <ctime>
#include <utility>

using namespace std;

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

const int MAXN = 100005;
const int MAXL = 22;

typedef vector<int> Graph[MAXN];
typedef vector<int> :: iterator IT;

Graph G;
int Euler[MAXN];
int n, m, L[MAXN << 1], RMQ[MAXL][MAXN<<1], First[MAXN], Lg[MAXN], K;

inline void DFs(int node, int lvl)
{
    Euler[++K] = node;
    L[K] = lvl;
    First[node] = K;
    for(IT it = G[node].begin(), fin = G[node].end(); it != fin ; ++ it)
    {
        DFs(*it, lvl+1);
        Euler[++K] = node;
        L[K] = lvl;
    }
}

inline int Lca(int x, int y)
{
    int diff, l, sol, sh;
    int a = First[x];
    int b = First[y];
    if(a>b)
        swap(a, b);
    diff = b - a + 1;
    l = Lg[diff];
    sol = RMQ[l][a];
    sh = diff - ( 1 << l);
    if(L[sol] > L[RMQ[l][a + sh]])
        sol = RMQ[l][a + sh];
    return Euler[sol];
}

inline void Build_RMQ()
{
    for(int i = 1 ; i <= K ; ++ i)
        RMQ[0][i] = i;
    for(int i = 1 ; (1 << i) < K ; ++ i)
        for(int j = 1 ; j <= K - (1 << i ) ; ++ j)
        {
            int l = 1<<(i-1);
            RMQ[i][j] = RMQ[i-1][j];
            if(L[RMQ[i-1][j + l]] < L[RMQ[i][j]])
                RMQ[i][j] = RMQ[i-1][j + l];
        }
}

inline void Build_Log()
{
    for(int i = 2 ; i <= K ; ++ i)
        Lg[i] = Lg[i >> 1] + 1;
}

int main()
{
    cin >> n >> m;
    for(int i = 1 ; i != n ; ++ i)
    {
        int x;
        cin >> x ;
        G[x].push_back(i+1);
    }

    DFs(1, 0);
    Build_Log();
    Build_RMQ();

    for( ; m ; -- m)
    {
        int x, y;
        cin >> x >> y;
        cout << Lca(x, y) << "\n";
    }

    return 0;
}