Cod sursa(job #3299034)

Utilizator EricDimiCismaru Eric-Dimitrie EricDimi Data 3 iunie 2025 23:06:06
Problema Lowest Common Ancestor Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.43 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 = 20;

int rmq[MAX_LOG + 1][MAX_N << 2 | 1];
int pos[MAX_LOG + 1][MAX_N << 2 | 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];

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;
    }
}

void init() {
    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] = niv[i];
        pos[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];
                pos[p][i] = pos[p - 1][i];
                continue;
            }
            if (rmq[p - 1][i] > rmq[p - 1][i + (1 << (p - 1))]) {
                rmq[p][i] = rmq[p - 1][i + (1 << (p - 1))];
                pos[p][i] = pos[p - 1][i + (1 << (p - 1))];
            } else {
                rmq[p][i] = rmq[p - 1][i];
                pos[p][i] = pos[p - 1][i];
            }
        }
}

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 (rmq[len][l] < rmq[len][r - (1 << len) + 1])
        posmin = pos[len][l];
    else
        posmin = pos[len][r - (1 << len) + 1];
    return euler[posmin];
}

int main() {
    read();
    dfs(1, 0);
    
    auto debug = [&]() {
        cout << "    Euler: ";
        for (int i = 1; i <= k; i++)
            cout << euler[i] << " ";
        cout << "\n";
        cout << " Adancime: ";
        for (int i = 1; i <= k; i++)
            cout << niv[i] << " ";
    };
    
    debug();
    init();
    
    while (m--) {
        fin >> u >> v;
        fout << lca(u, v) << "\n";
    }
    
    fin.close();
    fout.close();
    return 0;
}