Cod sursa(job #1341938)

Utilizator ArmandNMArmand Nicolicioiu ArmandNM Data 13 februarie 2015 11:53:30
Problema Lowest Common Ancestor Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 1.47 kb
#include <fstream>
#include <vector>

const int NMAX = 100005;
const int LMAX = 20;

using namespace std;

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

int N,M,x,y,K;
int First[NMAX];
int H[2*NMAX],L[2*NMAX],Lg[2*NMAX];
int rmq[LMAX][4*NMAX];
vector <int> v[NMAX];

void citire()
{
    f >> N >> M;
    for (int i = 2; i <= N; ++i)
    {
        f >> x;
        v[x].push_back(i);
    }
}

void DFS(int nod, int level)
{
    H[++K] = nod;
    L[K] = level;
    First[nod] = K;

    for (int i = 0; i < v[nod].size(); ++i)
    {
        int vecin = v[nod][i];
        DFS(vecin,level+1);
        H[++K] = nod;
        L[K] = level;
    }
}

void RMQ()
{
    for (int i = 2; i <= K; ++i)
        Lg[i] = Lg[i>>1] + 1;

    for (int i = 1; i <= K; ++i)
        rmq[0][i] = i;

    for (int i = 1; i < Lg[K]; ++i)
    {
        for (int j = 1; j <= K-(1<<Lg[i])+1; ++j)
        {
            int l = 1 << (i-1);

            rmq[i][j] = rmq[i-1][j];
            if (L[ rmq[i-1][j+l] ] < L[ rmq[i][j] ])
                rmq[i][j] = rmq[i-1][j+l];

        }
    }
}

int LCA(int x, int y)
{
    int a = First[x];
    int b = First[y];
    if (a > b) swap(a,b);

    int dist = b-a+1;
    int l = Lg[dist];

    int sol = rmq[l][a];
    if (L[ rmq[l][b-(1<<l)+1] ] < L[ sol ])
        sol = rmq[l][b-(1<<l)+1];

    return H[sol];

}

int main()
{
    citire();
    DFS(1,0);
    RMQ();

    while(M--)
    {
        f >> x >> y;
        g << LCA(x,y) << '\n';
    }

    f.close();
    g.close();

    return 0;
}