Cod sursa(job #3262682)

Utilizator AndreiNicolaescuEric Paturan AndreiNicolaescu Data 11 decembrie 2024 11:30:29
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.8 kb
#include <fstream>
#include <vector>
using namespace std;
ifstream cin("lca.in");
ofstream cout("lca.out");
const int Lmax = 20;
const int Nmax = 200001;
int n, m, x, y, st, dr;
vector<vector<int>> graf, r;
vector<int> viz, first, d, euler, E;
void dfs(int node, int h)
{
    euler.push_back(node);
    viz[node] = 1;
    d[node] = h;
    first[node] = euler.size() - 1;
    for(auto next:graf[node])
        if(!viz[next])
        {
            dfs(next, h + 1);
            euler.push_back(node);
        }
}
void precalc()
{
    for(int i=0; i<euler.size(); i++)
        r[0][i] = euler[i];
    int s = euler.size();
    for(int p=1; p < 20; p++)
        for(int i=0; i + (1 << p) <= s; i++)
        {
            int left = r[p-1][i];
            int right = r[p-1][i + (1 << (p - 1))];
            if(d[left] < d[right])
                r[p][i] = left;
            else
                r[p][i] = right;
        }
    for(int i=2; i<=s; i++)
        E[i] = E[i/2] + 1;
}
int main()
{
    cin >> n >> m;
    graf.assign(n+1, vector<int>());

    d.resize(n+1);
    viz.resize(n+1);
    first.assign(n+1, -1);

    for(int i=2; i<=n; i++)
    {
        cin >> x;
        graf[x].push_back(i);
        graf[i].push_back(x);
    }
    dfs(1, 1);
    E.resize(euler.size() + 1);
    r.assign(Lmax, vector<int>(euler.size(), 0));
    precalc();
    while(m--)
    {
        cin >> st >> dr;
        st = first[st];
        dr = first[dr];
        if(st > dr)
            swap(st, dr);
        int exp = E[dr - st + 1];
        int left = r[exp][st];
        int right = r[exp][dr - (1<<exp) + 1];
        int ans = 0;
        if(d[left] < d[right])
            ans = left;
        else
            ans = right;
        cout << ans << '\n';
    }
    return 0;
}