Cod sursa(job #1960885)

Utilizator andreigasparoviciAndrei Gasparovici andreigasparovici Data 10 aprilie 2017 19:02:42
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 1.56 kb
#include <bits/stdc++.h>

using namespace std;

const int MAXN =  100001;

int n, m, tata[MAXN], copil[MAXN];
vector<pair<int, int> >euler;
vector<int> tree[MAXN];
int dp[20][MAXN];
int pozitie[MAXN];

void citire()
{
    freopen("lca.in","r",stdin);
    scanf("%d %d",&n,&m);

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

void dfs(int nod,int niv)
{
    if(!pozitie[nod])
        pozitie[nod] = euler.size();
    euler.push_back({nod, niv+1});
    for(int it : tree[nod])
    {
        dfs(it, niv+1);
        euler.push_back({nod, niv+1});
    }
}

void build_rmq()
{
    int n = euler.size() - 1;
    for(int i=1;i<=n;i++)
        dp[0][i] = i;

    for(int i=1;(1<<i) <= n; i++)
    {
        for(int j=1;j<=n-(1<<i)+1;j++)
        {
            int power = 1<<(i-1);
            if(euler[dp[i-1][j]].second < euler[dp[i-1][j+power]].second)
                dp[i][j] = dp[i-1][j];
            else dp[i][j] = dp[i-1][j+power];
        }
    }
}

int query(int inc, int sf)
{
    int x = pozitie[inc], y = pozitie[sf];
    if(x > y)
        swap(x,y);

    int d = y - x + 1;
    int log2d = log2(d);

    if(euler[dp[log2d][x]].second < euler[dp[log2d][x + d - (1<<log2d)]].second)
        return dp[log2d][x];
    return dp[log2d][x + d - (1<<log2d)];
}

int main()
{
    citire();
    euler.push_back({0,0});
    dfs(1, 0);
    build_rmq();
    freopen("lca.out","w",stdout);
    while(m--)
    {
        int a, b;
        scanf("%d %d",&a,&b);
        printf("%d\n",euler[query(a,b)].first);
    }
    return 0;
}