Cod sursa(job #2759534)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 18 iunie 2021 22:15:49
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.44 kb
/*
    Sursa experimentala
*/

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

#define NMAX 100000 //o suta de mii

using namespace std;

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

struct element{
    int nod;
    int height;
};

int dimE;
int first[NMAX + 1], last[NMAX + 1];

element e[2 * NMAX - 1 + 1];
element tree[4 * 2 * (NMAX - 1) + 1];

int tt[NMAX + 1];
vector <int> v[NMAX + 1];

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

    first[nod] = dimE;
    last[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;

        last[nod] = dimE;
    }
}

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;
    }
}

void buildArbore(int node, int left, int right){
    if(left == right){
        tree[node] = e[left];
        return;
    }

    int mid = left + (right - left) / 2;

    buildArbore(node * 2, left, mid);
    buildArbore(node * 2 + 1, mid + 1, right);

    tree[node] = rezultant(tree[node * 2], tree[node * 2 + 1]);
}

int A, B; ///
element queryArbore(int node, int left, int right){
    if(A <= left && right <= B){
        return tree[node];
    }

    int mid = left + (right - left) / 2;

    element rez1, rez2;
    int OK1 = 0, OK2 = 0;
    if(A <= mid){
        rez1 = queryArbore(node * 2, left, mid);
        OK1 = 1;
    }
    if(B >= mid + 1){
        rez2 = queryArbore(node * 2 + 1, mid + 1, right);
        OK2 = 1;
    }

    if(OK2 == 0){
        return rez1;
    }
    else if(OK1 == 0){
        return rez2;
    }
    else {
        return rezultant(rez1, rez2);
    }
}

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

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

    buildEuler();
    buildArbore(1, 1, dimE);


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

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

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

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

        fout << queryArbore(1, 1, dimE).nod << "\n";

        //printf("\n");
    }

    return 0;
}