Cod sursa(job #2271848)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 29 octombrie 2018 12:08:36
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.79 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX=1e6+5;

vector <int> G[NMAX];

int N, M, i, X, u, v, cnt=0;

int RMQ[31][2*NMAX];

int position[NMAX];

bool pus[NMAX];

struct Euler
{
    int Nod, Nivel;
};

Euler A[NMAX];

int log2 (int N)
{
    int p2=1;
    int exp=0;

    while(p2<N)
    {
        p2*=2;
        exp++;
    }

    if(p2>N)
        exp--;
    return exp;
}

void DFS (int Nod, int Nivel)
{
    pus[Nod]=true;

    A[++cnt].Nod=Nod;
    A[cnt].Nivel=Nivel;

    position[Nod]=cnt;

    for(int i=0; i<G[Nod].size(); i++)
        if(pus[G[Nod][i]]==false)
        {
            pus[G[Nod][i]]=true;

            DFS(G[Nod][i], Nivel+1);

            A[++cnt].Nod=Nod;
            A[cnt].Nivel=Nivel;
        }
}

void precalculation ()
{
    int M=2*N-1;

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

    for(int i=1; i<=log2(M); i++)
        for(int j=1; j<=(M-(1<<i)+1); j++)
        {
            if(A[RMQ[i-1][j+(1<<(i-1))]].Nivel < A[RMQ[i-1][j]].Nivel)
                RMQ[i][j]=RMQ[i-1][j+(1<<(i-1))];

            else RMQ[i][j]=RMQ[i-1][j];
        }
}

int Query (int u, int v)
{
    int i=position[u];
    int j=position[v];

    if(i==j)
        return A[i].Nod;
    else
    {
        if(i>j)
            swap(i, j);

        int K=0;

        K=log2(j-i+1);

        if(A[RMQ[K][i]].Nivel < A[RMQ[K][j-(1<<K)+1]].Nivel)
            return A[RMQ[K][i]].Nod;
        else return A[RMQ[K][j-(1<<K)+1]].Nod;
    }
}

int main()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    scanf("%d%d", &N, &M);

    for(i=2; i<=N; i++)
    {
        scanf("%d", &X);

        G[X].push_back(i);
    }

    DFS(1, 1);

    precalculation();

    for(i=1; i<=M; i++)
    {
        scanf("%d%d", &u, &v);

        printf("%d\n", Query(u, v));
    }

    return 0;
}