Cod sursa(job #3298875)

Utilizator EricDimiCismaru Eric-Dimitrie EricDimi Data 2 iunie 2025 20:42:26
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.31 kb
/**
  Solutie: Arbori de intervale
  Complexitate: O(n + m log n)
*/
#include <bits/stdc++.h>

using namespace std;

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

const int INF = 2'000'000'000;
const int MAX_DIM = 100'000;

int euler[MAX_DIM << 1];/// euler[i] - al i-lea nod in parcurgerea Euler
int niv[MAX_DIM << 1];  /// height[i] - nivelul nodului euler[i]
int firstPos[MAX_DIM];  /// firstPos[i] - prima pozitie a nodului i in parcurgere
int aint[MAX_DIM << 4]; /// nodul pentru care se atinge min{height[st..dr]}
int k;

vector<int> G[MAX_DIM]; /// arborele cu radacina in 1

int n, m;

void dfs(int nod, int dist) { /// parcurgerea euleriana / Euler tour
    euler[++k] = nod;
    niv[k] = dist;
    firstPos[nod] = k;
    
    for (int vec : G[nod]) {
        dfs(vec, dist + 1);
        
        euler[++k] = nod;
        niv[k] = dist;
    }
}

void build(int nod, int st, int dr) {
    if (st == dr) {
        /// nodul st are adancimea minima
        aint[nod] = st;
        return;
    }
    int mid = (st + dr) >> 1;
    build(nod << 1, st, mid);
    build(nod << 1 | 1, mid + 1, dr);
    if (niv[aint[nod << 1]] <= niv[aint[nod << 1 | 1]])
        aint[nod] = aint[nod << 1];
    else
        aint[nod] = aint[nod << 1 | 1];
}

void query(int nod, int st, int dr, int a, int b, int &sol, int &niv_sol) {
    if (a <= st && dr <= b) {
        if (niv[aint[nod]] < niv_sol) {
            sol = euler[aint[nod]];
            niv_sol = niv[aint[nod]];
        }
        return;
    }
    int mid = (st + dr) >> 1;
    if (a <= mid)
        query(nod << 1, st, mid, a, b, sol, niv_sol);
    if (b > mid)
        query(nod << 1 | 1, mid + 1, dr, a, b, sol, niv_sol);
}

int lca(int u, int v) {
    int st = firstPos[u], dr = firstPos[v];
    if (st > dr) {
        int aux = st;
        st = dr;
        dr = st;
    }
    int sol = INF, niv_sol = INF;
    query(1, 1, k, st, dr, sol, niv_sol);
    return sol;
}

int main() {
    fin >> n >> m;
    for (int i = 2; i <= n; i++) {
        int x;
        fin >> x;
        G[x].push_back(i);
    }
    
    dfs(1, 0);
    build(1, 1, k);
    
    while (m--) {
        int u, v;
        fin >> u >> v;
        fout << lca(u, v) << "\n";
    }
    
    fin.close();
    fout.close();
    return 0;
}