Cod sursa(job #2984649)

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

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

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

struct LowestCommonAncestor
{
    int height[NMAX];
    int first[NMAX];
    vector<int> euler;
    int t[8 * NMAX];
    vector<bool> visited;

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

    void build(int v, int tl, int tr)
    {   
        if (tl == tr)
        {
            t[v] = euler[tl];
        }
        else
        {
            int tm = (tl + tr) / 2;
            build(2 * v, tl, tm);
            build(2 * v + 1, tm + 1, tr);
            t[v] = (height[t[2 * v]] < height[t[2 * v + 1]]) ? t[2 * v] : t[2 * v + 1];
        }
    }

    int query(int v, int tl, int tr, int l, int r)
    {
        if (r < l)
        {
            return -1;
        }
        if (tl == l && tr == r)
        {
            return t[v];
        }
        int tm = (tl + tr) / 2;
        int l_ans = query(2 * v, tl, tm, l, min(tm, r));
        int r_ans = query(2 * v + 1, tm + 1, tr, max(tm + 1, l), r);
        if (l_ans == -1)
        {
            return r_ans;
        }
        if (r_ans == -1)
        {
            return l_ans;
        }
        return height[l_ans] < height[r_ans] ? l_ans : r_ans;
    }

    void init()
    {
        height[1] = 1;
        visited.assign(n + 1, false);
        euler.push_back(-1); // pt indexare de la 1
        dfs(1);
        build(1, 1, euler.size() - 1);
    }

    int lca(int u, int v)
    {
        int left = first[u];
        int right = first[v];
        if (left > right)
        {
            swap(left, right);
        }
        return query(1, 1, euler.size() - 1, left, right);
    }
} 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;
}