Cod sursa(job #1960441)

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

using namespace std;

const int SIZE = 100000, MAXN =  100001;

#define fastcall __attribute__((optimize("-O3")))
#define inline __inline__ __attribute__((always_inline))

struct InParsare
{

    char buffer[SIZE];
    int index;
    inline fastcall char next_char()
    {
        if(index == SIZE)
        {
            fread(buffer,1,SIZE,stdin);
            index = 0;
            return next_char();
        }
        return buffer[index++];
    }
    InParsare()
    {
        freopen("lca.in","r",stdin);
        index = 0;
        fread(buffer,1,SIZE,stdin);
    }
    inline fastcall InParsare& operator >> (int &x)
    {
        x = 0;
        char c;
        for(c = next_char(); c < '0' || c > '9'; c = next_char());
        for(;c >= '0' && c <= '9'; c = next_char())
            x = x * 10 + c - '0';
        return *this;
    }
}in;

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

inline fastcall void citire()
{
    in>>n>>m;
    tata[1] = 1;

    for(int i = 2; i <= n; i++)
    {
        in>>tata[i];
        tree[i].push_back(tata[i]);
        tree[tata[i]].push_back(i);
    }
}

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

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

    for(int i=1;(1<<i) <= n; i++)
    {
        for(int j=1;j<=n-(1<<i)+1;j++)
        {
            int power = 1<<(i-1);
            dp[i][j] = min(dp[i-1][j],dp[i-1][j+power]);
        }
    }
}

inline fastcall int query(int inc, int sf)
{
    int x = pozitie[inc], y = pozitie[sf];
    if(x > y)
        swap(x,y);
    return min(dp[((int)log2(y-x+1))][x],dp[((int)log2(y-x+1))][x+((y-x+1) - (1<<((int)log2(y-x+1))))]);
}

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