Cod sursa(job #1803357)

Utilizator andreiugravuFMI Andrei Zugravu andreiugravu Data 11 noiembrie 2016 12:28:55
Problema Lowest Common Ancestor Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 1.99 kb
//LCA - Lowest Common Ancestor

#include <fstream>

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;
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(int i = 2 ; i <= n ; i++) {
        if(noduri[i] == nod) {
            parcurgereEuler(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 dif, len, sol, sh;

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

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

int main()
{
    int i;

    fin>>n>>m;
    for(i = 2 ; i <= n ; i++)
        fin>>noduri[i];

    parcurgereEuler(1, 0);
    rmq();

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

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

    return 0;
}