Cod sursa(job #1950825)

Utilizator CraiuAndrei Craiu Craiu Data 3 aprilie 2017 12:08:11
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.62 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");

const int nmax = 200005;
int n,m,v[nmax],len,dp[nmax],poz[nmax],lg[nmax];
int rmq[20][nmax];
vector < int > L[nmax];

inline void Read()
{
    int i, x;
    fin >> n >> m;
    for(i = 2; i <= n; i++)
    {
        fin >> x;
        L[x].push_back(i);
    }
}

inline void Dfs(int nod, int level)
{
    v[++len] = nod;
    poz[nod] = len;
    dp[nod] = level;
    for(auto it : L[nod])
    {
        Dfs(it, level + 1);
        v[++len] = nod;
    }
}

inline void Rmq()
{
    int i, lgmax, j, lgpow;
    for(i = 2; i <= 2 * n; i++)
        lg[i] = lg[i / 2] + 1;
    for(i = 1; i <= len; i++)
        rmq[0][i] = i;
    lgmax = lg[len];
    for(j = 1; j <= lgmax; j++)
    {
        lgpow = (1 << (j - 1));
        for(i = 1; i + 2 * lgpow <= len; i++)
        {
            rmq[j][i] = rmq[j - 1][i];
            if(dp[v[rmq[j][i]]] > dp[v[rmq[j - 1][i + lgpow]]])
                rmq[j][i] = rmq[j - 1][i + lgpow];
        }
    }
}

inline int Query(int x, int y)
{
    int l, k, kpow, sol;
    l = y - x + 1;
    k = lg[l];
    kpow = (1 << k);
    sol = rmq[k][x];
    if(dp[v[sol]] > dp[v[rmq[k][y + 1 - kpow]]])
        sol = rmq[k][y - kpow];
    return v[sol];
}

inline void Solve()
{
    int i, x, y, st, dr;
    for(i = 1; i <= m; i++)
    {
        fin >> x >> y;
        st = min(poz[x], poz[y]);
        dr = max(poz[x], poz[y]);
        fout << Query(st, dr) << "\n";
    }
}

int main()
{
    Read();
    Dfs(1, 0);
    Rmq();
    Solve();
    return 0;
}