Cod sursa(job #2858619)

Utilizator qweryclujRadu Alexandru qwerycluj Data 27 februarie 2022 23:32:04
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.39 kb
#include <bits/stdc++.h>

using namespace std;

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

vector<vector<int>> graf;
int n, m;

vector<pair<int, int>> eulerian;
vector<int> occurance;
int RMQ[200005][20];

void dfs(int nod, int nivel)
{
    eulerian.push_back({nod, nivel});
    // pozitia la ultimul elem
    occurance[nod] = eulerian.size() - 1;

    for(int i: graf[nod])
    {
        dfs(i, nivel + 1);
        eulerian.push_back({nod, nivel});
    }
}

void gen_RMQ()
{
    for(int i = 0 ; i < eulerian.size(); i++)
    {
        //initializam cu valoarea acelui nod pt ca in RMQ tinem indici
        RMQ[i][0] = i;
    }

    for(int i = 1; i <= log(eulerian.size()); i++)
    {
        for(int j = 0; j + (1 << i) < eulerian.size(); j++)
        {
            if(eulerian[RMQ[j][i - 1]].second < eulerian[RMQ[j + (1 << (i-1))][i - 1]].second) 
            {
                RMQ[j][i] = RMQ[j][i - 1];
            }
            else 
            {
                RMQ[j][i] = RMQ[j + (1 << (i-1))][i - 1];
            }
        }
    }
}

void citire()
{
    fin >> n >> m;
    int tata;
    graf = vector<vector<int>>(n + 1);
    occurance = vector<int>(n + 1);

    for(int i = 2; i <= n; i++)
    {
        fin >> tata;
        graf[tata].push_back(i);
    }
}

int main()
{
    citire();
    dfs(1,0);
    gen_RMQ();
    int n1, n2;
    int sol;
    int log_dist;
    for(int i = 0; i < m ;i ++)
    {
        fin >> n1 >> n2;
        // trebuie sa stim care e mai mare
        if(occurance[n1] > occurance[n2])
        {
            log_dist = log(occurance[n1]-occurance[n2]);
            // aflam minimul dintre cele 2 jumatati
            if(eulerian[RMQ[occurance[n2]][log_dist]].second < eulerian[RMQ[occurance[n1] - (1 << log_dist)][log_dist]].second)
            {
                sol = RMQ[occurance[n2]][log_dist];
            }
            else
            {
                sol = RMQ[occurance[n1]-(1 << log_dist)][log_dist];
            }
        }
        else
        {
            log_dist = log(occurance[n2]-occurance[n1]);
            if(eulerian[RMQ[occurance[n1]][log_dist]].second < eulerian[RMQ[occurance[n2] - (1 << log_dist)][log_dist]].second)
            {
                sol = RMQ[occurance[n1]][log_dist];
            }
            else
            {
                sol = RMQ[occurance[n2] - (1 << log_dist)][log_dist];
            }
        }
        fout << eulerian[sol].first << '\n';
    }
}