Cod sursa(job #3040449)

Utilizator Cosmin1605Damian Cosmin Cosmin1605 Data 29 martie 2023 21:26:03
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.79 kb
#include <iostream>
#include <fstream>
#include <vector>
#define NMAX 100005
#define MAXLOG 20
using namespace std;

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

struct RmqItem{
    int nod;
    int nivel;
};
RmqItem rmq[MAXLOG][2*NMAX];
vector <int> arb[NMAX];
int n, m, tata, nod1, nod2, pcurent, pstart[NMAX], exp[2*NMAX];

void dfs(int nod, int niv){
    rmq[0][++pcurent] = {nod, niv};
    pstart[nod] = pcurent;

    for(int i = 0; i < arb[nod].size(); i++){
        dfs(arb[nod][i], niv+1);
        rmq[0][++pcurent] = {nod, niv};
    }
}

// Exponentul celei mai mari puteri ale lui 2 mai mici sau egale cu i
void calculExponent(){
    exp[1] = 0;
    for(int i = 2; i <= pcurent; i++){
        exp[i] = 1 + exp[i/2];
    }
}

void calculRMQ(){
    int pmax = exp[pcurent];
    for(int p = 1; p <= pmax; p++){
        for(int i = 1; i <= pcurent; i++){
            int j = i + (1 << (p-1));
            rmq[p][i] = rmq[p-1][i];
            if(j <= pcurent && rmq[p-1][j].nivel < rmq[p][i].nivel){
                rmq[p][i] = rmq[p-1][j];
            }
        }
    }
}

int LCA(int x, int y){
    int poz_x = pstart[x];
    int poz_y = pstart[y];

    if(poz_x > poz_y){
        swap(poz_x, poz_y);
    }

    int lungime = poz_y - poz_x + 1;
    int e = exp[lungime];
    int l = (1 << e);

    RmqItem st = rmq[e][poz_x];
    RmqItem dr = rmq[e][poz_y - l + 1];

    return (st.nivel < dr.nivel) ? st.nod : dr.nod;
}

int main()
{
    in >> n >> m;
    for(int nod = 2; nod <= n; nod++){
        in >> tata;
        arb[tata].push_back(nod);
    }

    dfs(1,1);
    calculExponent();
    calculRMQ();

    for(int i = 1; i <= m; i++){
        in >> nod1 >> nod2;
        out << LCA(nod1, nod2) << '\n';
    }

    return 0;
}