Cod sursa(job #2984675)

Utilizator Matei_MunteanuMunteanu Matei Ioan Matei_Munteanu Data 24 februarie 2023 17:17:28
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.18 kb
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 100004;
const int K = 18;

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

int n, m, q;
vector<int> adj[NMAX];

struct LowestCommonAncestor
{
    vector<int> euler;
    vector<bool> visited;
    int height[NMAX];
    int first[NMAX];
    int st[2 * NMAX][K];
    int lg2[2 * NMAX];

    void dfs(int v)
    {
        visited[v] = true;
        first[v] = euler.size();
        euler.push_back(v);
        for (int u : adj[v])
        {
            if (!visited[u])
            {
                height[u] = height[v] + 1;
                dfs(u);
                euler.push_back(v);
            }
        }
    }

    void precompute_lg2()
    {
        lg2[1] = 0;
        for (int i = 2; i <= m; i++)
        {
            lg2[i] = lg2[i / 2] + 1;
        }
    }

    void init_sparse_table()
    {
        precompute_lg2();
        for (int i = 0; i < m; i++)
        {
            st[i][0] = euler[i];
        }
        for (int i = 1; i <= K; i++)
        {
            for (int j = 0; j + (1 << i) - 1 < m; j++)
            {
                st[j][i] = height[st[j][i - 1]] < height[st[j + (1 << (i - 1))][i - 1]] ? st[j][i - 1] : st[j + (1 << (i - 1))][i - 1];
            }
        }
    }

    void init()
    {
        height[1] = 1;
        visited.assign(n + 1, false);
        dfs(1);
        m = euler.size();
        init_sparse_table();
    }

    int get_min(int l, int r)
    {
        int lg = lg2[r - l + 1];
        return height[st[l][lg]] <  height[st[r - (1 << lg) + 1][lg]] ? st[l][lg] : st[r - (1 << lg) + 1][lg];
    }

    int lca(int u, int v)
    {
        int l = first[u];
        int r = first[v];
        if (r < l)
        {
            swap(l, r);
        }
        return get_min(l, r);
    }
} LCA;

int main()
{
    fin >> n >> q;
    for (int i = 2; i <= n; i++)
    {
        int a;
        fin >> a;
        adj[a].push_back(i);
        adj[i].push_back(a);
    }
    LCA.init();
    for (int i = 1; i <= q; i++)
    {
        int a, b;
        fin >> a >> b;
        fout << LCA.lca(a, b) << '\n';
    }
    return 0;
}