Cod sursa(job #2774388)

Utilizator vlad2009Vlad Tutunaru vlad2009 Data 11 septembrie 2021 15:16:43
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.22 kb
#include <fstream>
#include <vector>

using namespace std;

const int Nmax = 100000;
int h[Nmax + 1], l[Nmax + 1];
pair <int, int> aint[8 * Nmax + 1];
vector <int> adj[Nmax + 1];
vector <int> euler;
bool viz[Nmax + 1];
int n, k = 1;

void dfs(int node, int q = 0)
{
    viz[node] = true;
    euler.push_back(node);
    l[node] = euler.size();
    h[node] = q;
    for (auto u : adj[node])
    {
        if (!viz[u])
        {
            dfs(u, q + 1);
            euler.push_back(node);
        }
    }
}

void build(int node, int l, int r)
{
    if (l == r)
    {
        aint[node] = {h[euler[l - 1]], euler[l - 1]};
    }
    else
    {
        int mid = (l + r) / 2;
        build(2 * node, l, mid);
        build(2 * node + 1, mid + 1, r);
        if (aint[2 * node].first <= aint[2 * node + 1].first)
        {
            aint[node] = aint[2 * node];
        }
        else
        {
            aint[node] = aint[2 * node + 1];
        }
    }
}

pair <int, int> query(int node, int l, int r, int p, int q)
{
    if (p > q)
    {
        return make_pair(-1, -1);
    }
    else if (l == p && r == q)
    {
        return aint[node];
    }
    else
    {
        int mid = (l + r) / 2;
        pair <int, int> qry1 = query(2 * node, l, mid, p, min(mid, q));
        pair <int, int> qry2 = query(2 * node + 1, mid + 1, r, max(p, mid + 1), q);
        if (qry1.first == -1)
        {
            return qry2;
        }
        else if (qry2.first == -1)
        {
            return qry1;
        }
        if (qry1.first <= qry2.first)
        {
            return qry1;
        }
        else
        {
            return qry2;
        }
    }
}

int lca(int u, int v)
{
    pair <int, int> p = query(1, 1, n, min(l[u], l[v]), max(l[u], l[v]));
    return p.second;
}

int main()
{
    ifstream fin("lca.in");
    ofstream fout("lca.out");
    int m;
    fin >> n >> m;
    for (int i = 2; i <= n; i++)
    {
        int nr;
        fin >> nr;
        adj[nr].push_back(i);
    }
    dfs(1);
    n = euler.size();
    build(1, 1, n);
    while (m--)
    {
        int u, v;
        fin >> u >> v;
        fout << lca(u, v) << "\n";
    }
    return 0;
}