Cod sursa(job #1805800)

Utilizator andreiugravuFMI Andrei Zugravu andreiugravu Data 14 noiembrie 2016 14:14:40
Problema Lowest Common Ancestor Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.07 kb
//LCA - Lowest Common Ancestor

#include <fstream>
#include <vector>

using namespace std;

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

#define NMAX 100000
#define MMAX 2000000
#define MAXL 20

int n, m, x, y, crt;
vector <int> noduri[NMAX]; //vectorul de noduri
int euler[2*NMAX]; //parcurgerea euler
int level[2*NMAX]; //vectorul de niveluri
int poz[NMAX]; //vectorul de pozitii
int lg[2*NMAX];
int RMQ[MAXL][4*NMAX];

void parcurgereEuler(int nod, int nivel) {
    euler[++crt] = nod; //nodul este adaugat in reprezentarea Euler a arborelui
    level[crt] = nivel; //retinem nivelul fiecarei pozitii din reprezentarea Euler a arborelui
    poz[nod] = crt; //retinem prima aparitie a fiecarui nod in reprezentarea Euler a arborelui

    for(unsigned i = 0 ; i < noduri[nod].size() ; i++) {
            parcurgereEuler(noduri[nod][i], nivel+1);
            euler[++crt] = nod;
            level[crt] = nivel;
    }
}

void rmq() {
    int i, j, k;

    for(i = 2 ; i <= crt ; i++)
        lg[i] = lg[i/2] + 1; //initializare

    for(i = 1 ; i <= crt ; i++)
        RMQ[0][i] = i; //initializare

    for(i = 1 ; (1 << i) < crt ; i++)
        for(j = 1 ; j <= crt - (1 << i) ; j++) {
            k = 1 << (i - 1);
            RMQ[i][j] = RMQ[i-1][j];
            if(level[RMQ[i-1][j+k]] < level[RMQ[i][j]])
                RMQ[i][j] = RMQ[i-1][j+k];
        }
}

int lca(int x, int y) {
    int a = poz[x], b = poz[y], aux;
    int len, sol;

    if(a > b) { aux = a; a = b; b = aux; }

    len = lg[b-a+1];
    sol = RMQ[len][a];

    if(level[sol] > level[RMQ[len][b - (1 << len) + 1]])
        sol = RMQ[len][b - (1 << len) + 1];
    return euler[sol];
}

int main()
{
    int i;

    fin>>n>>m;
    noduri[0].push_back(0);
    noduri[0].push_back(1);
    for(i = 1 ; i < n ; i++) {
        fin>>x;
        noduri[x].push_back(i+1);
    }

    parcurgereEuler(1, 0);
    rmq();

    for(i = 1 ; i <= m ; i++) {
        fin>>x>>y;
        fout<<lca(x, y)<<endl;
    }

    fin.close();
    fout.close();

    return 0;
}