Cod sursa(job #2332590)

Utilizator petru.ciocirlanPetru Ciocirlan petru.ciocirlan Data 30 ianuarie 2019 21:32:13
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.86 kb
#include <fstream>
#include <vector>
using namespace std;

#define FILENAME "lca"
ifstream fin (FILENAME".in");
ofstream fout(FILENAME".out");

const int MAXN = 100000 + 16;
const int MAXLOGN = 20;

int N, M, K;
int E[MAXN << 1], L[MAXN << 1], H[MAXN], Log[MAXN << 1];
int RMQ[MAXLOGN][MAXN << 2];

vector < int > G[MAXN];

void citire();
void E_precalc(int, int);
void RMQ_precalc();
int RMQ_query(int, int);

int main()
{
    citire();
    E_precalc(1, 0);
    RMQ_precalc();

    while(M--)
    {
        int x, y;
        fin >> x >> y;
        fout << RMQ_query(x, y) << '\n';
    }

    return 0;
}

int RMQ_query(int x, int y)
{
    int Result = 0, diff, len, sh;
    x = H[x], y = H[y];
    if(x > y)
        swap(x, y);
    diff = y - x + 1;
    len = Log[diff];
    Result = RMQ[len][x];
    sh = diff - (1 << len);
    if(L[Result] > L[ RMQ[len][x + sh] ] )
        Result = RMQ[len][x + sh];

    return E[Result];
}

void RMQ_precalc()
{
    for(int i = 2; i <= K; ++i)
        Log[i] = Log[i>>1] + 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 + (1 << i) - 1 <= K; ++j)
        {
            int len = 1 << (i - 1);

            RMQ[i][j] = RMQ[i-1][j];
            if(L[ RMQ[i-1][j + len] ] < L[ RMQ[i][j] ])
                RMQ[i][j] = RMQ[i-1][j + len];
        }
}

void E_precalc(int node, int level)
{
    ++K;
    E[K] = node;
    L[K] = level;
    H[node] = K;

    vector < int > :: iterator it;
    for(it = G[node].begin(); it != G[node].end(); ++it)
    {
        E_precalc(*it, level + 1);

        ++K;
        E[K] = node;
        L[K] = level;
    }
}

void citire()
{
    fin >> N >> M;

    for(int i = 2; i <= N; ++i)
    {
        int x;
        fin >> x;
        G[x].push_back(i);
    }
}