Cod sursa(job #3338613)

Utilizator AnSeDraAndrei Sebastian Dragulescu AnSeDra Data 4 februarie 2026 12:11:56
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.39 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

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

const int Nmax = 100005;
const int Qmax = 100005;
const int Log2Nmax = 17;

struct nod{
    int val;
    vector<int> vecini;
    int timp_initial, timp_final;
    int timp_rmq, adancime;
};

struct pozitie_rmq{
    int adancime, nod;

    bool operator < (pozitie_rmq x){
        return adancime < x.adancime;
    }
};

int n, q, timp = 0, timp_rmq = 0;
int euler[2 * Nmax];
pozitie_rmq rmq_euler[Log2Nmax][2 * Nmax];
nod arbore[Nmax];

pozitie_rmq min(pozitie_rmq a, pozitie_rmq b){
    if(a < b){
        return a;
    }
    return b;
}

void citire_arbore(){
    int nod;

    fin >> n >> q;

    for(int i = 2; i <= n; i++){
        fin >> nod;
        arbore[i].vecini.push_back(nod);
        arbore[nod].vecini.push_back(i);
    }
}

void liniarizare_euler(int nod, int parinte){
    euler[++timp] = nod;
    arbore[nod].timp_initial = timp;

    rmq_euler[0][++timp_rmq] = {arbore[nod].adancime, nod};
    arbore[nod].timp_rmq = timp_rmq;

    for(int vecin : arbore[nod].vecini){
        if(vecin != parinte){
            arbore[vecin].adancime = arbore[nod].adancime + 1;
            liniarizare_euler(vecin, nod);

            rmq_euler[0][++timp_rmq] = {arbore[nod].adancime, nod};
        }
    }

    euler[++timp] = nod;
    arbore[nod].timp_final = timp;
}

void calculare_rmq(){
     for(int bit = 1; (1 << bit) <= timp; bit++){
        for(int i = 1; i <= timp - (1 << bit) + 1; i++){
            rmq_euler[bit][i] = min(rmq_euler[bit - 1][i], rmq_euler[bit - 1][i + (1 << (bit - 1))]);
        }
    }
}

pozitie_rmq rmq_query(int poz1, int poz2){
    int ordin = log2(poz2 - poz1);
    return min(rmq_euler[ordin][poz1], rmq_euler[ordin][poz2 - (1 << ordin) + 1]);
}

int lca(int nod1, int nod2){
    return rmq_query(arbore[nod1].timp_rmq, arbore[nod2].timp_rmq).nod;
}

void citire_si_rezolvare_interogari(){
    int nod1, nod2;

    for(int i = 1; i <= q; i++){
        fin >> nod1 >> nod2;

        if(arbore[nod1].timp_rmq > arbore[nod2].timp_rmq){
            swap(nod1, nod2);
        }

        fout << lca(nod1, nod2) << '\n';
    }
}

int main(){
    citire_arbore();
    liniarizare_euler(1, 0);
    calculare_rmq();

    citire_si_rezolvare_interogari();

    return 0;
}