Cod sursa(job #1822157)

Utilizator LaurIleIle Laurentiu Daniel LaurIle Data 4 decembrie 2016 13:28:10
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.51 kb
#include <iostream>
#include <fstream>
#include <vector>
#define NMAX 100005
#define LMAX 20
using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

vector <int> G[100005];
int n, m, k;
int nivel[2*NMAX], eul[2*NMAX], first[2*NMAX], Lg[2*NMAX], RMQ[LMAX][2*NMAX];

void read()
{
    f >> n >> m;
    for(int i=2, x; i<=n; ++i)
    {
        f >> x;
        G[x].push_back(i);
    }
}

void dfs(int nod, int niv)
{
    eul[++k]=nod;
    nivel[k]=niv;
    first[nod]=k;
    for(int i=0; i<G[nod].size(); ++i)
    {
        dfs(G[nod][i], niv+1);
        eul[++k]=nod;
        nivel[k]=niv;
    }
}

void rmq()
{

    for(int i=2; i<=k; ++i)
    {
        Lg[i]=Lg[i/2]+1;
    }

    for(int i=1; i<=k; ++i)
        RMQ[0][i]=i;

    for(int i=1; (1<<i)<k; ++i)
    {
       for(int j=1; j<=k-(1<<i); ++j)
       {
           int l=(1<<i-1);
           RMQ[i][j]=RMQ[i-1][j];
           if(nivel[RMQ[i-1][j+l]] < nivel[RMQ[i][j]])
            RMQ[i][j]=RMQ[i-1][j+l];
       }
    }
}

int lca(int x, int y)
{
    int dif, l, rez, dr;
    int a=first[x], b=first[y];
    if(a>b) swap(a,b);
    dif=b-a+1;
    l=Lg[dif];
    rez = RMQ[l][a];
    dr = dif-(1 << l);
    if(nivel[rez]>nivel[RMQ[l][a+dr]])
        rez=RMQ[l][a+dr];
    return eul[rez];

}

int main()
{
    read();
    dfs(1,0);
    rmq();
    while(m--)
    {
        int x, y;
        f >> x >> y;
        g << lca(x,y)<< '\n';
    }
    f.close();
    g.close();
    return 0;
}