Cod sursa(job #3330211)

Utilizator mirceamaierean41Mircea Maierean mirceamaierean41 Data 18 decembrie 2025 02:37:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.41 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<int> eul;
vector<int> ap;

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

void DFS(int x)
{
    ap[x] = eul.size();
    eul.push_back(x);
    for (auto &y : g[x])
    {
        DFS(y);
        eul.push_back(x);
    }
}

int getNodeWithMinDepth(int a, int b)
{
    if (ap[a] < ap[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] = eul[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 = ap[left];
    right = ap[right];
    if (left > right)
        swap(left, right);
    int i = lg[right - left + 1];
    return getNodeWithMinDepth(rmq[i][left], rmq[i][right - (1 << i) + 1]);
}

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