Cod sursa(job #2871033)

Utilizator meinkampfEmanuel Pinzariu meinkampf Data 12 martie 2022 20:08:19
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.25 kb
#include <bits/stdc++.h>
using namespace std;

ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> L[200003];
int n, m, p, e[200003], niv[200003], poz[100003];
int rmq[21][200003], p2[200003];
/*
e - retine nodurile in ordinea parcurgerii Euler
niv[i] = nivelul pe care se afla nodul e[i] , i=1..p
i=1..n, poz[i] = o pozitie unde se gaseste nodul i in e[]

p2[i] = lungimea putere a lui 2 maxima a unui interval care
       are lungimea i
rmq[i][j] = pozitia minimului din intervalul [j, j+2^i-1]
i = 0,1,...k, unde 2^k <= p

p = lungimea parcurgerii euler

1 2 3 4 5 6 7 8 9 10
6 4 2 1 7 5 8 6 3 7

     1 2 3 4 5 6 7 8 9
p2 = 0 1 1 2 2 2 2 3 3


Reprezentarea Euler :  1  2  4  7  4  8  4  2  5  2  6  9  6  2  1  3  10  3  11  3  1
Nivelul             :  0  1  2  3  2  3  2  1  2  1  2  3  2  1  0  1   2  1   2  1  0
*/

void Citire()
{
    int i, j;
    fin >> n >> m;
    for (i = 2; i <= n; i++)
    {
        fin >> j;
        L[j].push_back(i);
    }
}

void Euler(int k, int nivel)
{
    e[++p] = k;
    niv[p] = nivel;
    poz[k] = p;
    for (auto w : L[k])
    {
        Euler(w, nivel + 1);
        e[++p] = k;
        niv[p] = nivel;
    }
}

void RMQ() // range minimum query
{
    int i, j;
    p2[1] = 0;
    for (i = 2; i <= p; i++)
        p2[i] = 1 + p2[i / 2]; // vectorul de puteri
    for (i = 1; i <= p; i++)
        rmq[0][i] = i; // intervalul (i, i)
    //
    for (i = 1; (1 << i) <= p; i++)
        for (j = 1; j <= p - (1 << i) + 1; j++)
        {
            int len = (1 << (i - 1));
            rmq[i][j] = rmq[i - 1][j];
            if (niv[rmq[i - 1][j]] > niv[rmq[i - 1][j + len]]) 
                rmq[i][j] = rmq[i - 1][j + len];
        }
}

void Ques()
{
    int i, j, ex, len, s1, s2;
    // interogarile : 
    while (m--)
    {
        fin >> i >> j;
        i = poz[i]; j = poz[j];
        if (i > j) swap(i, j);
        //
        ex = p2[j - i + 1];
        len = (1 << ex);
        s1 = rmq[ex][i];
        s2 = rmq[ex][j - len + 1];
        //
        if (niv[s1] > niv[s2]) fout << e[s2] << "\n";
        else fout << e[s1] << "\n";
    }
}

int main()
{
    Citire();
    Euler(1, 1);
    RMQ();
    Ques();
    fout.close();
    return 0;
}