Cod sursa(job #2759556)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 18 iunie 2021 23:25:48
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.09 kb
/*
    Sursa experimentala
*/

#include <iostream>
#include <fstream>
#include <vector>

#define NMAX 100000 //o suta de mii
#define LOGMAX2 17

using namespace std;

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

struct element{
    int nod;
    int height;
};

int dimE;
int first[NMAX + 1];
element O[2 * NMAX][LOGMAX2 + 1];
element e[2 * NMAX];
vector <int> v[NMAX + 1];

void DFS(int nod, int height){
    dimE++;
    e[dimE].nod = nod;
    e[dimE].height = height;

    first[nod] = dimE;

    for(int i = 0; i < v[nod].size(); i++){
        int X = v[nod][i];

        DFS(X, height + 1);
        dimE++;
        e[dimE].nod = nod;
        e[dimE].height = height;
    }
}

inline void buildEuler(){
    DFS(1, 1); //stiu ca e radacina
}

element rezultant(element A, element B){
    if(A.height <= B.height){
        return A;
    }
    else {
        return B;
    }
}

inline void buildVector(){
    for(int i = dimE; i >= 1; i--){
        O[i][0] = e[i];
    }

    for(int i = dimE; i >= 1; i--){
        for(int j = 1; i + (1 << j) - 1 <= dimE; j++){
            O[i][j] = rezultant(O[i][j - 1], O[i + (1 << (j - 1)) ][j - 1]);
        }

    }
}


int putereDoiLowerbound(int x){
    int lo = -1;
    int hi = LOGMAX2 + 1;

    while(hi - lo > 1){
        int mid = lo + (hi - lo) / 2;

        if( (1 << mid) <= x ){
            lo = mid;
        }
        else {
            hi = mid;
        }
    }

    return lo;
}


int main()
{
    int N, M;
    fin >> N >> M;

    for(int i = 2; i <= N; i++){
        int x;
        fin >> x;
        v[ x ].push_back(i);
    }

    buildEuler();
    buildVector();


    for(int q = 1; q <= M; q++){
        //printf("q = %d\n", q);

        int a, b;
        fin >> a >> b;

        int A = first[a];
        int B = first[b];

        if(A > B){
            swap(A, B);
        }

        int k = putereDoiLowerbound(B - A + 1);
        fout << rezultant(O[A][k], O[B - (1 << k) + 1][k]).nod << "\n";

        //printf("\n");
    }

    return 0;
}