Cod sursa(job #2660294)

Utilizator Alin_StanciuStanciu Alin Alin_Stanciu Data 18 octombrie 2020 19:41:29
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.69 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

int n, m, cnt, T[100001], E[200001], I[100001], L[100001], Log2[100001];
vector<int> G[100001], Mi[22];

void Euler(int x)
{
    E[++cnt] = x;
    I[x] = cnt;
    for (int y : G[x])
    {
        if (y == T[x])
            continue;
        L[y] = L[x] + 1;
        Euler(y);
        E[++cnt] = x;
    }
}

void Prep()
{
    // Construiesc arborele.
    for (int i = 2; i <= n; ++i)
    {
        G[i].push_back(T[i]);
        G[T[i]].push_back(i);
    }

    // Turul Euler.
    Euler(1);

    // Construiesc Log2.
    for (int i = 2; i <= n; ++i)
        Log2[i] = Log2[i / 2] + 1;

    // Construiesc Mi pentru Rmq.
    Mi[0] = vector<int>(cnt + 1);
    for (int i = 1; i <= cnt; ++i)
        Mi[0][i] = E[i];
    int e = 1;
    while ((1 << e) <= cnt)
    {
        Mi[e] = vector<int>(cnt - (1 << e) + 2);
        for (int i = 1; i <= cnt - (1 << e) + 1; ++i)
        {
            if (L[Mi[e - 1][i]] < L[Mi[e - 1][i + (1 << (e - 1))]])
                Mi[e][i] = Mi[e - 1][i];
            else Mi[e][i] = Mi[e - 1][i + (1 << (e - 1))];
        }
        ++e;
    }
}

int Rmq(int a, int b)
{
    int e = Log2[b - a + 1];
    if (L[Mi[e][a]] < L[Mi[e][b - (1 << e) + 1]])
        return Mi[e][a];
    return Mi[e][b - (1 << e) + 1];
}

int main()
{
    fin >> n >> m;
    for (int i = 1; i < n; ++i)
        fin >> T[i + 1];

    Prep();

    for (int i = 1; i <= m; ++i)
    {
        int x, y;
        fin >> x >> y;
        fout << Rmq(min(I[x], I[y]), max(I[x], I[y])) << '\n';
    }

    return 0;
}