Cod sursa(job #2332549)

Utilizator petru.ciocirlanPetru Ciocirlan petru.ciocirlan Data 30 ianuarie 2019 20:50:43
Problema Lowest Common Ancestor Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.62 kb
#include <fstream>
#include <vector>
#include <cmath>
using namespace std;

#define FILENAME "lca"
ifstream fin (FILENAME".in");
ofstream fout(FILENAME".out");
const int MAXN = 100000 + 16;
const int MAXLOGN = 20;
int RMQ[MAXLOGN][MAXN];
int E[MAXN + MAXN], L[MAXN + MAXN], H[MAXN];
int N, M, K;
vector < int > Fii[MAXN];

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

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

    E_precalc(1, 0);
    RMQ_precalc();

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

    return 0;
}

int RMQ_query(int x, int y)
{
    int Result = 0;

    if(x > y)
        x ^= y, y ^= x, x ^= y;

    int len = log2(y - x + 1);
    Result = min(RMQ[len][x], RMQ[len][y - (1 << len) + 1]);
    Result = E[Result];

    return Result;
}

void RMQ_precalc()
{
    for(int i = 1; i <= K; ++i)
        RMQ[0][i] = i;

    for(int j = 1; (1 << j) <= K; ++j)
        for(int i = 1; i + (1 << j) - 1 <= K; ++i)
        {
            if(L[ RMQ[j-1][i] ] < L[ RMQ[j-1][i + (1 << (j-1))] ])
                RMQ[j][i] = RMQ[j-1][i];
            else
                RMQ[j][i] = RMQ[j-1][i + (1 << (j-1))];
        }
}

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

    if(!H[node])
        H[node] = K;

    for(auto i : Fii[node])
    {
        E_precalc(i, level + 1);
        ++K;
        E[K] = node;
        L[K] = level;
    }
}