Cod sursa(job #2961062)

Utilizator matei.tudoseMatei Tudose matei.tudose Data 5 ianuarie 2023 18:00:06
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.98 kb
#include <fstream>
#include <cmath>
#include <vector>

#define INF 0x3f3f3f3f
using namespace std;

ifstream cin("lca.in");
ofstream cout("lca.out");

vector<int> G[100005];

int pos[400005], n, q, rmq[20][400005], euler[400005], lvl[400005], sz;
bool used[100005];

void euler_init(int node, int level)
{
    used[node] = true;
    ++sz;
    euler[sz] = node;
    lvl[sz] = level;
    pos[node] = sz;

    for (auto it : G[node])
    {
        if (used[it])
        {
            continue;
        }

        euler_init(it, level + 1);
        ++sz;
        euler[sz] = node;
        lvl[sz] = level;
    }
}

void rmq_init()
{
    for (int i = 1; i <= sz; ++i)
    {
        rmq[0][i] = i;
    }

    for (int i = 1; (1 << i) <= sz; ++i)
    {
        for (int j = 1; j + (1 << i) <= sz; ++j)
        {
            if (lvl[rmq[i - 1][j]] <= lvl[rmq[i - 1][j + (1 << (i - 1))]])
            {
                rmq[i][j] = rmq[i - 1][j];
            }
            else
            {
                rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
            }
        }
    }
}

int query(int lft, int rgt)
{
    int line, skip, rmq_ans;
    skip = rgt - lft + 1;
    line = log2(skip);

    if (lvl[rmq[line][lft]] <= lvl[rmq[line][lft + skip - (1 << line)]])
    {
        rmq_ans = rmq[line][lft];
    }
    else
    {
        rmq_ans = rmq[line][lft + skip - (1 << line)];
    }

    return euler[rmq_ans];
}

int main()
{
    cin >> n >> q;

    for (int i = 2; i <= n; ++i)
    {
        int x;
        cin >> x;
        G[x].push_back(i);
    }

    euler_init(1, 0);
    rmq_init();

    /*for(int i = 0; i <= log2(lvl.size()); ++i) {
        for(int j = 1; j <= lvl.size(); ++j) {
            cout << rmq[i][j] << ' ';
        }

        cout << '\n';
    }*/

    for (int i = 1; i <= q; ++i)
    {
        int node1, node2;
        cin >> node1 >> node2;

        if (pos[node1] > pos[node2])
        {
            swap(node1, node2);
        }

        cout << query(pos[node1], pos[node2]) << '\n';
    }

    return 0;
}