Cod sursa(job #1838862)

Utilizator mdiannnaMarusic Diana mdiannna Data 1 ianuarie 2017 22:24:22
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.68 kb
#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <climits>


using namespace std;
int A[100010];
int E[10000000];
int H[10000000];
vector<int> Ch[100010];
int pos[100010];

int n, m;
int pos_euler;


int B[100005];
int N;

 int lung_bloc, nr_bloc;



void calcMin(){
    int j = 0;
    int minim = 0;
    int minim_pos = 0;

    for(int i=0; i<nr_bloc; i++){
        minim = H[j];
        minim_pos = j;
        for(int k=0; k<lung_bloc; k++){
            if(H[j] < minim){
                minim = H[j];
                minim_pos = j;
            }
            j++;
        }

        B[i] = minim_pos;
    }


}


int query(int st, int dr){

    int minim = H[st];
    int minim_pos = st;

    while((st % lung_bloc)!=0 && (st <= dr)){
        if(H[st] < minim){
            minim = H[st];
            minim_pos = st;
        }
        st++;
    }
    while(((dr+1)%lung_bloc!=0) && (dr > st)){
        if(H[dr] < minim){
            minim = H[dr];
            minim_pos = dr;
        }
        dr--;
    }

     int st_bloc = st/lung_bloc;
    int dr_bloc = dr/lung_bloc;


    if((st % lung_bloc==0) && (dr - st+1) >= lung_bloc )
        for(int i=st_bloc; i<=dr_bloc; i++){
            if(H[B[i]] < minim){
                minim = H[B[i]];
                minim_pos = B[i];
            }

        }


    return minim_pos;
}


void parcurgere_euleriana(int nod, int h){
    queue<int> Q;
    Q.push(nod);

    E[pos_euler] = nod;
    H[pos_euler] = h;

    pos[nod] = pos_euler;
    pos_euler++;

    while(!Q.empty()){
        int nod = Q.front();


        for(vector<int>::iterator  it = Ch[nod].begin(); it!=Ch[nod].end(); it++){
           parcurgere_euleriana(*it, h+1);
            E[pos_euler] = nod;

             H[pos_euler] = h;
            pos_euler++;

        }


        Q.pop();

    }
}

void afisEuler(){
    for(int i=0; i<pos_euler; i++)
        cout << E[i] << " ";
    cout << endl;

    cout << "H:" << endl;
    for(int i=0; i<pos_euler; i++)
        cout << H[i] << " ";
    cout << endl;


}

int minimEuler(int a, int b){
    pos_a = pos[a];
    pos_b = pos[b];


    if(pos_a > pos_b)
        swap(pos_a, pos_b);

    int minim_pos = query(pos_a, pos_b);

    return minim_pos;

}

int main()
{
    freopen("lca.in", "r", stdin);
    freopen("lca.out", "w", stdout);

    scanf("%d %d", &n, &m);

    for(int i=1; i<n; i++)
    {
        cin >> A[i];
        Ch[A[i]].push_back(i+1);
    }



    parcurgere_euleriana(1, 0);
   // afisEuler();

    N = pos_euler;

    lung_bloc = sqrt(N);
    nr_bloc = N/lung_bloc;


    calcMin();

    int a, b;
    for(int i=0; i<m; i++){
        scanf("%d %d", &a, &b);
        printf("%d\n", E[minimEuler(a, b)] );
    }

    return 0;
}