Cod sursa(job #2622566)

Utilizator VictorVrabieVrabie Victor VictorVrabie Data 1 iunie 2020 15:02:05
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.15 kb
#include <cstdio>
#include <vector>


#define MAX_NODES 100009
#define MAX_EDGES 2000009
#define LOG_N 17


std::vector<int> g_euler_tour;
std::vector<int> g_first_occurence(MAX_NODES);
std::vector<int> g_node_level(MAX_NODES);
std::vector<int> g_graph[MAX_NODES];

int number_of_nodes;
int number_of_requests;

int g_precomputed_minimum[2 * MAX_NODES][LOG_N];
int g_log[2 * MAX_NODES];


void dfs(int p_root, int p_level)
{
    g_first_occurence[p_root] = g_euler_tour.size();
    g_euler_tour.push_back(p_root);
    g_node_level[p_root] = p_level;
    
    for (auto& i : g_graph[p_root])
    {
        dfs(i, p_level + 1);
        g_euler_tour.push_back(p_root);
    } 
}


int get_node_with_minimum_high(int i, int j)
{
    return (g_node_level[i] < g_node_level[j]) ? i : j;
}

void precompute()
{
    for (int i = 0; i < g_euler_tour.size(); ++i)
    {
        g_precomputed_minimum[i][0] = g_euler_tour[i];
    }

    for (int j = 1; j <= LOG_N; ++j)
    {
        for (int i = 0; i + (1 << j) <= g_euler_tour.size(); ++i)
        {
            g_precomputed_minimum[i][j] = get_node_with_minimum_high(g_precomputed_minimum[i][j - 1], g_precomputed_minimum[i + (1 << (j - 1))][j - 1]);
        }
    }
}


int get_lca(int l, int r)
{   
    int first = g_first_occurence[l];
    int second = g_first_occurence[r];

    if (first > second)
        std::swap(first, second);

    int l_interval_legth = g_log[second - first + 1];
    return get_node_with_minimum_high(g_precomputed_minimum[first][l_interval_legth], 
        g_precomputed_minimum[second - (1 << l_interval_legth) + 1][l_interval_legth]);
}

int main()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    scanf("%d%d", &number_of_nodes, &number_of_requests);

    int l_temp_var{};
    for (int i = 0; i < number_of_nodes - 1; ++i)
    {   
        scanf("%d", &l_temp_var);
        g_graph[l_temp_var].push_back(i + 2);
    }

    dfs(1, 0);

    for (int i = 2; i < g_euler_tour.size(); ++i)
        g_log[i] = g_log[i >> 1] + 1;

    precompute();

    int x{}, y{};

    while (number_of_requests--)
    {
        scanf("%d%d", &x, &y);
        printf("%d\n", get_lca(x, y));
    }

    return 0;
}