Cod sursa(job #2908317)

Utilizator CaptnBananaPetcu Tudor CaptnBanana Data 2 iunie 2022 20:06:28
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.7 kb
#include <fstream>
#include <iostream>

using namespace std;

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

const int N = 1e5 + 1, LOG = 17;
int n, m, x, y;
int log[N], nivel[N], t[LOG][N]; // t[e][i] = al 2^e-lea stramos as lui i

void nivelul(int nod){
    if(nivel[nod])
        return;

    nivelul(t[0][nod]);
    nivel[nod] = nivel[t[0][nod]] + 1;
}

void calculeaza(){
    for(int i = 2; i <= n; i++)
        log[i] = 1 + log[i / 2];

    for(int e = 1; e < LOG; e++){
        for(int i = 1; i <= n; i++){
            t[e][i] = t[e - 1][t[e - 1][i]];
        }
    }

    nivel[1] = 1; // 1 e radacina
    for(int i = 2; i <= n; i++)
        nivelul(i);
}

// returneaza stramosul de un anumit ordin al lui x
int stramos(int x, int ordin){
    /*while(ordin--)   -------------------- dar asta e O(ordin) si putem face O(log2(ordin))
        x = t[0][x];*/

    int e = 0;
    while(ordin){
        if(ordin % 2)
            x = t[e][x];

        e++;
        ordin /= 2;
    }

    return x;
}

int lca(int x, int y){
    int e = log[nivel[x]]; // nivel[x] == nivel[y]
    while(e >= 0){
        if(t[e][x] != t[e][y]){
            x = t[e][x];
            y = t[e][y];
        }

        e--;
    }

    return t[0][x]; // stiu ca t[0][x] == t[0][y]
}

int main(){
    f >> n >> m;
    for(int i = 2; i <= n; i++)
        f >> t[0][i];

    calculeaza();
    while(m--){
        f >> x >> y;
        if(nivel[x] > nivel[y])
            swap(x, y);

        y = stramos(y, nivel[x] - nivel[y]);
        if(x == y){
            g << x << '\n';
            continue;
        }

        g << lca(x, y) << '\n';
    }

    f.close();
    g.close();
}