Cod sursa(job #2707384)

Utilizator vlad_butnaruVlad Butnaru vlad_butnaru Data 16 februarie 2021 21:11:07
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.96 kb
#include <bits/stdc++.h>
using namespace std;
ifstream in ("lca.in");
ofstream out ("lca.out");
int n, q;
vector <int> v[102010];
vector <pair <int , int> > euler;
pair <int , int> rmq[20][202001];
int first_ap[102001];
int lgg[102001];
void dfs (int nod, int nivel)
{
    euler.push_back({nod, nivel});
    for (auto i: v[nod])
    {
        dfs(i,nivel + 1);
        if (v[nod].size())
            euler.push_back({nod, nivel});
    }
}
void preq ()
{
    lgg[1] = 0;
    for (int i = 2;i<=100000;++i)
        lgg[i] = lgg[i/2] + 1;
    for (int i = 1;i<euler.size();++i)
    {
        rmq[0][i].first = euler[i].second;
        rmq[0][i].second = euler[i].first;
    }
    for (int i = 1;i <= 20;++i)
    {
        int k = euler.size() - (1<<i);
        for (int j = 1; j <= k;++j)
        {

            if (rmq[i-1][j].first < rmq[i-1][j + (1<<(i-1))].first)
            {
                rmq[i][j].first = rmq[i-1][j].first;
                rmq[i][j].second = rmq[i-1][j].second;
            }
            else
            {
                rmq[i][j].first = rmq[i-1][j + (1<<(i-1))].first;
                rmq[i][j].second = rmq[i-1][j + (1<<(i-1))].second;
            }
        }
    }
}
int query (int st, int dr)
{
    int lv = lgg[dr - st + 1];
    if (rmq[lv][st].first < rmq[lv][dr - (1<<lv) + 1].first)
        return rmq[lv][st].second;
    else
        return rmq[lv][dr - (1<<lv) + 1].second;
}
int main ()
{
    in >> n >> q;
    for (int i = 2;i<=n; ++i)
    {
        int a;
        in >> a;
        v[a].push_back(i);
    }
    euler.push_back({0,0});
    dfs(1, 0);
    preq();
    for (int i = 1;i<euler.size();++i)
        if (first_ap[euler[i].first]==0)
            first_ap[euler[i].first] = i;
    for (int i = 1;i<=q;++i)
    {
        int a, b;
        in >> a >> b;
        a = first_ap[a];
        b = first_ap[b];
        out << query (min (a,b), max(a,b)) << '\n';
    }
    return 0;
}