Cod sursa(job #3306292)

Utilizator vlad082002Ciocoiu Vlad vlad082002 Data 9 august 2025 12:57:22
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.15 kb
#include <fstream>
#include <set>
#include <queue>
#include <iostream>

using namespace::std;

int n, m;
int visited[100005];

vector<int> eulerTour;
vector<int> eulerTourLevels;
vector<int> firstOccInEuler;
vector<int> lg;

vector<int> edges[100005];

int rmq[32][200005];


void dfs(int node, int level) {
    firstOccInEuler[node] = eulerTour.size();
    for (int &child: edges[node]) {
        eulerTour.push_back(node);
        eulerTourLevels.push_back(level);
        dfs(child, level + 1);
    }
    eulerTour.push_back(node);
    eulerTourLevels.push_back(level);
}

int lca(int p, int q) {
    int firstP = firstOccInEuler[p];
    int firstQ = firstOccInEuler[q];
    if (firstQ < firstP) swap(firstP, firstQ);

    int diff = firstQ - firstP;
    int diffLog = lg[diff];

    int ans = rmq[diffLog][firstP];
    if(eulerTourLevels[ans] > eulerTourLevels[rmq[diffLog][firstQ - (1 << diffLog)]]) ans = rmq[diffLog][firstQ - (1 << diffLog)];

    return eulerTour[ans];
}

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

    vector<int> parent;
    parent.push_back(0);
    parent.push_back(0);

    fin >> n >> m;
    firstOccInEuler.resize(n + 1);

    for(int i = 2; i <= n; i++) {
        int x;
        fin >> x;
        parent.push_back(x);
        edges[x].push_back(i);
    }

    // construct euler tour and levels
    dfs(1, 0);

    // for(int &node: eulerTour) cout << node << ' ';
    // cout << '\n';

    // build sparse table
    for(int j = 0; j < eulerTour.size(); j ++) rmq[0][j] = j;
    for(int i = 1; (1 << i) <= eulerTour.size(); i ++) {
        for (int j = 0; j + (1 << i) < eulerTour.size(); j ++) {
            rmq[i][j] = rmq[i-1][j];
            if (eulerTourLevels[rmq[i-1][j + (1 << (i-1))]] < eulerTourLevels[rmq[i][j]]) 
                rmq[i][j] = rmq[i-1][j + (1 << (i-1))];
            // cout << i << ' ' << j <<  ' ' << rmq[i][j] << '\n'; 
        }
    }

    // // construct logarithms
    lg.resize(eulerTour.size());
    lg[1] = 0;
    for(int i = 2; i < eulerTour.size(); i++) lg[i] = lg [i / 2] + 1;

    // answer rmq queries
    while (m--) {
        int p, q;
        fin >> p >> q;

        fout << lca(p, q) << '\n';
    }
}