Cod sursa(job #1690082)

Utilizator lupvasileLup Vasile lupvasile Data 14 aprilie 2016 19:12:28
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.51 kb
#include <bits/stdc++.h>
using namespace std;
#ifdef INFOARENA
#define cout fout
ifstream fin("lca.in");
ofstream fout("lca.out");
#else
ifstream fin("date.in");
#endif // INFOARENA

/// ///////////////////////////////////////////

void read();

#define nmax 100010
#define emax 100010
#define inf 0x3f3f3f3f
#define logmax 18

int n,lev[nmax],m,first_ap[nmax],posEuler;
vector<int> G[nmax];
int rmq[logmax][emax],llog[emax];

int lca(int x,int y)
{
    if(first_ap[x]>first_ap[y]) swap(x,y);

    int diff = first_ap[y] - first_ap[x] + 1;
    int log=llog[diff];

    x=first_ap[x],y=first_ap[y];

    return lev[rmq[log][x]] < lev[rmq[log][y-(1<<log)+1]] ? rmq[log][x]:rmq[log][y-(1<<log)+1];
}

void make_rmq()
{
    int i,k;
    for(i=2;i<=posEuler;++i)
        llog[i] = llog[i>>1]+1;

    for(k=1;k<=llog[posEuler];++k)
        for(i=1;i+(1<<k)-1<=posEuler;++i)
            rmq[k][i] = lev[rmq[k-1][i]] < lev[rmq[k-1][i+(1<<(k-1))]] ? rmq[k-1][i]:rmq[k-1][i+(1<<(k-1))];
}

void dfs(int nod)
{
    ++lev[nod];

    first_ap[nod]=++posEuler;
    rmq[0][posEuler]=nod;

    for(auto son:G[nod])
    {
        lev[son]=lev[nod];
        dfs(son);
        rmq[0][++posEuler]=nod;
    }
}

int main()
{
    read();

    dfs(1);

    make_rmq();

    int x,y;
    for(;m;--m)
    {
        fin>>x>>y;
        cout<<lca(x,y)<<'\n';
    }
}
void read()
{
    int x,y,c,i;
    fin>>n>>m;
    for(i=2;i<=n; ++i)
    {
        fin>>x;
        G[x].push_back(i);
    }
}