Cod sursa(job #3199927)

Utilizator robert_dumitruDumitru Robert Ionut robert_dumitru Data 2 februarie 2024 20:50:34
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.73 kb
#include <bits/stdc++.h>
using namespace std;

/*
e = retinem parcurgerea Euler
niv[i] = pe ce nivel se afla nodul e[i]
  in arbore
P[i] = o pozitie unde se afla nodul i in e

rmq[i][j] = valoarea minima din niv[j..j+2^i-1]
i=0..log2(m)
j = 1..m-2^i+1

expo[i] = p: exponentul maxim p cu 2^p<=i
*/

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

int n, m, Q;
vector<int> L[200005];
int e[200005], niv[200005], P[200005], expo[200005];
int rmq[20][200005];

void Euler(int k, int level)
{
    e[++m] = k;
    P[k] = m;
    niv[m] = level;
    for (int i : L[k])
    {
        Euler(i, level + 1);
        e[++m] = k;
        niv[m] = level;
    }
}

void BuildRMQ()
{
    int i, j, L, A, B;
    for (i = 2; i <= m; i++)
        expo[i] = expo[i / 2] + 1;
    
    for (i = 1; i <= m; i++)
        rmq[0][i] = i;

    for (i = 1; i <= expo[m]; i++)
    {
        L = (1 << i);
        for (j = 1; j <= m - L + 1; j++)
        {
            A = rmq[i - 1][j];
            B = rmq[i - 1][j + L / 2];

            if (niv[A] <= niv[B])
                rmq[i][j] = A;
            else 
                rmq[i][j] = B;
        }
    }
}

void LCA(int A, int B)
{
    int E, L, Lca;
    A = P[A]; B = P[B];

    if (A > B)
        swap(A, B);

    E = expo[B - A + 1];
    L = (1 << E);

    A = rmq[E][A];
    B = rmq[E][B - L + 1];
    if (niv[A] <= niv[B])   
        Lca = A;
    else 
        Lca = B;
    fout << e[Lca] << "\n";
}

int main()
{
    int i, j;
    fin >> n >> Q;
    for (i = 2; i <= n; i++)
    {
        fin >> j;
        L[j].push_back(i);
    }
    Euler(1, 1);
    BuildRMQ();
    while (Q--)
    {
        fin >> i >> j;
        LCA(i, j);
    }
}