Cod sursa(job #2120967)

Utilizator razvan99hHorhat Razvan razvan99h Data 3 februarie 2018 10:27:48
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.78 kb
#include <iostream>
#include <fstream>
#include <vector>
#define DM 100005
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
int n, m, u, v, dim, eul[DM*2], lvl[DM*2], first[DM*2], rmq[20][DM*2], log[DM*2];
vector <int> g[DM];

void dfs(int nod, int level)
{
    dim++;
    eul[dim]=nod;
    lvl[dim]=level;
    first[nod]=dim;
    for(auto it:g[nod])
    {
        dfs(it,level+1);
        dim++;
        eul[dim]=nod;
        lvl[dim]=level;
    }
}
void build_rmq()
{
    //in rmq[i][j] va fi nodul de nivel minim dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui
    log[0]=-1;
    for(int i=1;i<=dim;i++)
        log[i]=1+log[i>>1];
    for(int i=1;i<=dim;i++)
        rmq[0][i]=i;

    for(int k=1;k<=log[dim];k++)
        for(int i=1;i<=dim-(1<<k);i++)
        {
            int l=(1<<(k-1));
            if(lvl[rmq[k-1][i+l]] < lvl[rmq[k-1][i]])
                rmq[k][i]=rmq[k-1][i+l];
            else rmq[k][i]=rmq[k-1][i];
        }
}

int lca(int u, int v)
{
    //Cel mai apropiat strămoş comun a 2 noduri este nodul de nivel minim dintre primele apariţii ale nodurilor din query din reprezentarea Euler a arborelui.
    int l, i, rez;
    u=first[u];
    v=first[v];
    if(u>v)
        swap(u,v);
    l=log[v-u+1];
    if(lvl[rmq[l][u]] < lvl[rmq[l][v-(1<<l)+1]])
        return eul[rmq[l][u]];
    else return eul[rmq[l][v-(1<<l)+1]];
}
int main()
{
    fin>>n>>m;
    for(int i=2;i<=n;i++)
    {
        fin>>u;
        g[u].push_back(i);
    }
    dfs(1,0);
    build_rmq();
    /*for(int k=0;k<=log[dim];k++)
        {for(int i=1;i<=dim;i++) cout<<rmq[k][i]<<' '; cout<<endl;}*/

    for(int i=1;i<=m;i++)
    {
        fin>>u>>v;
        cout<<lca(u,v)<<'\n';
    }
    return 0;
}