Cod sursa(job #3330316)

Utilizator mirceamaierean41Mircea Maierean mirceamaierean41 Data 18 decembrie 2025 17:51:49
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.52 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 1e5 + 1;
const int KMAX = 20;

vector<int> g[NMAX];
vector<pair<int, int>> eul;
vector<int> f, lvl;

int rmq[KMAX][2 * NMAX];
int lg[2 * NMAX];

void DFS(int x)
{
    f[x] = eul.size();
    eul.push_back({lvl[x], x});
    for (auto &y : g[x])
    {
        lvl[y] = lvl[x] + 1;
        DFS(y);
        eul.push_back({lvl[x], x});
    }
}

int getNodeWithMinDepth(int a, int b)
{
    if (eul[a] < eul[b])
        return a;
    return b;
}

void computeRMQ()
{
    for (int i = 2; i < eul.size(); ++i)
        lg[i] = lg[i / 2] + 1;

    for (int i = 1; i < eul.size(); ++i)
        rmq[0][i] = i;

    for (int i = 1; (1 << i) < eul.size(); ++i)
        for (int j = 1; j + (1 << i) - 1 < eul.size(); ++j)
            rmq[i][j] = getNodeWithMinDepth(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]);
}

int query(int left, int right)
{
    left = f[left];
    right = f[right];
    if (left > right)
        swap(left, right);
    int i = lg[right - left + 1];
    return eul[getNodeWithMinDepth(rmq[i][left], rmq[i][right - (1 << i) + 1])].second;
}

int main()
{
    int n, q;
    fin >> n >> q;
    f.resize(n + 1);
    lvl.resize(n + 1);
    int t;
    for (int i = 2; i <= n; ++i)
    {
        fin >> t;
        g[t].push_back(i);
    }
    lvl[1] = 0;
    eul.push_back({0, 0});
    DFS(1);
    computeRMQ();
    int x, y;
    while (q--)
    {
        fin >> x >> y;
        fout << query(x, y) << '\n';
    }
    return 0;
}