Cod sursa(job #3299039)

Utilizator EricDimiCismaru Eric-Dimitrie EricDimi Data 3 iunie 2025 23:12:28
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.91 kb
/**
    Solutie: rmq
    Complexitate: O(n log n + m)
*/
#include <bits/stdc++.h>

using namespace std;

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

const int MAX_N = 100'000;
const int MAX_LOG = 19;

int rmq[MAX_LOG + 1][(MAX_N << 1) | 1];
int lg2[(MAX_N << 1) | 1];

int euler[(MAX_N << 1) | 1];
int niv[(MAX_N << 1) | 1];
int first[MAX_N + 1];

int n, m, k, x, u, v;

vector<int> G[MAX_N + 1];

void read() {
    fin >> n >> m;
    for (int i = 2; i <= n; i++) {
        fin >> x;
        G[x].push_back(i); /// x este tatal lui i
    }
}

void dfs(int nod, int dist) {
    euler[++k] = nod;
    niv[k] = dist;
    first[nod] = k;
    for (int vec : G[nod]) {
        dfs(vec, dist + 1);
        euler[++k] = nod;
        niv[k] = dist;
    }
}

int lca(int u, int v) {
    int posmin = 0;
    int l = first[u], r = first[v];
    if (l > r) {
        int aux = l;
        l = r;
        r = aux;
    }
    int len = lg2[r - l + 1];
    if (niv[rmq[len][l]] < niv[rmq[len][r - (1 << len) + 1]])
        posmin = rmq[len][l];
    else
        posmin = rmq[len][r - (1 << len) + 1];
    return euler[posmin];
}

int main() {
    read();
    dfs(1, 0);
    
    lg2[1] = 0;
    for (int i = 2; i <= k; i++)
        lg2[i] = lg2[i >> 1] + 1;
    
    for (int i = 1; i <= k; i++)
        rmq[0][i] = i;
    
    for (int p = 1; p <= lg2[k]; p++)
        for (int i = 1; i <= k; i++) {
            if (i > k - (1 << p) + 1) {
                rmq[p][i] = rmq[p - 1][i];
                continue;
            }
            if (niv[rmq[p - 1][i]] > niv[rmq[p - 1][i + (1 << (p - 1))]])
                rmq[p][i] = rmq[p - 1][i + (1 << (p - 1))];
            else
                rmq[p][i] = rmq[p - 1][i];
        }
    
    while (m--) {
        fin >> u >> v;
        fout << lca(u, v) << "\n";
    }
    
    fin.close();
    fout.close();
    return 0;
}