Cod sursa(job #3342740)

Utilizator MrPetcuPetcu Robert MrPetcu Data 25 februarie 2026 14:51:16
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.52 kb
#include <vector>
#include <fstream>

using namespace std;

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

int num_noduri, num_queries;

int tata;
vector<int> adiacenta[100000 + 5];

int nod_1, nod_2;

struct element_euler{
    int valoare, nivel;
};

vector<element_euler> euler_tour;
int prima_aparitie[100000 + 5];

void initialize(){
    euler_tour.push_back({0, 0});
    for(int i = 1; i <= num_noduri; i++){
        prima_aparitie[i] = 1e9;
    }
}

void build_euler_tour(int nod = 1, int nivel = 1){
    euler_tour.push_back({nod, nivel});
    prima_aparitie[nod] = min(prima_aparitie[nod], (int)euler_tour.size() - 1);
    for(int fiu : adiacenta[nod]){
        build_euler_tour(fiu, nivel + 1);
        euler_tour.push_back({nod, nivel});
    }
}

int putere_2[200000 + 5];

vector<element_euler> rmq[200000 + 5];

void generate_puteri_2(){
    putere_2[1] = 0;
    for(int i = 2; i <= 2 * num_noduri; i++){
        putere_2[i] = putere_2[i / 2] + 1;
    }
}

void build_rmq(){
    for(int i = 1; i < euler_tour.size(); i++){
        rmq[i].push_back(euler_tour[i]);
    }
    for(int exponent = 1; exponent <= putere_2[euler_tour.size() - 1]; exponent++){
        int pow_2 = (1 << exponent);
        for(int i = 1; i + pow_2 < euler_tour.size(); i++){
            element_euler st = rmq[i][exponent - 1];
            element_euler dr = rmq[i + pow_2 / 2][exponent - 1];
            if(st.nivel <= dr.nivel){
                rmq[i].push_back(st);
            }
            else{
                rmq[i].push_back(dr);
            }
        }
    }
}

element_euler minim(int capat_st, int capat_dr){
    int lungime = capat_dr - capat_st + 1;
    int exponent = putere_2[lungime];
    int pow_2 = (1 << exponent);
    element_euler st = rmq[capat_st][exponent];
    element_euler dr = rmq[capat_dr - pow_2 + 1][exponent];
    if(st.nivel <= dr.nivel){
        return st;
    }
    else{
        return dr;
    }
}

int main(){
    fin >> num_noduri >> num_queries;
    for(int i = 2; i <= num_noduri; i++){
        fin >> tata;
        adiacenta[tata].push_back(i);
    }

    initialize();
    build_euler_tour();

    generate_puteri_2();
    build_rmq();

    for(int i = 1; i <= num_queries; i++){
        fin >> nod_1 >> nod_2;
        int capat_st = min(prima_aparitie[nod_1], prima_aparitie[nod_2]);
        int capat_dr = max(prima_aparitie[nod_1], prima_aparitie[nod_2]);
        fout << minim(capat_st, capat_dr).valoare << '\n';
    }

    return 0;
}