Cod sursa(job #1497955)

Utilizator Master011Dragos Martac Master011 Data 7 octombrie 2015 20:14:30
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.78 kb
#include<cstdio>
using namespace std;

const int nMax = 100005, lMax = 20;
int val[nMax], urm[nMax], lst[nMax], e[nMax * 2], nivel[nMax * 2], rmq[lMax][nMax * 2], prim[nMax], lg[nMax * 2];
int n, m, k;


void dfs(int nod, int lv){
    e[++k] = nod;
    prim[nod] = k;
    rmq[0][k] = k;
    nivel[k] = lv;

    int u = lst[nod], vec = val[u];

    while(u){
        dfs(vec, lv + 1);
        e[++k] = nod;
        rmq[0][k] = k;
        nivel[k] = lv;

        u = urm[u];
        vec = val[u];
    }
}

int minim(int a, int b){
    return a < b ? a : b;
}

void mRmq(){
    for(int i = 2 ; i <= k ; ++i) lg[i] = lg[i >> 1] + 1;

    for(int i = 1 ; i <= lg[k] ; ++i){
        for(int j = 1 ; j <= k - (1 << i) + 1 ; ++j){
            if(nivel[rmq[i - 1][j]] < nivel[rmq[i - 1][j + (1 << (i - 1))]]){
                rmq[i][j] = rmq[i - 1][j];
            }else{
                rmq[i][j] = rmq[i - 1][j + (1 << (i - 1))];
            }
        }
    }
}

int lca(int a, int b){
    a = prim[a];
    b = prim[b];
    if(a > b){
        int aux = a;
        a = b;
        b = aux;
    }

    int diff = b - a + 1;
    int l = lg[diff];

    if(nivel[rmq[l][a]] < nivel[rmq[l][a + diff - (1<< l)]]){
        return e[rmq[l][a]];
    }
    return e[rmq[l][a + diff - (1<< l)]];
}

int main (){
    FILE *in = fopen("lca.in","r");
    fscanf(in,"%d%d",&n,&m);

    for(int i = 2, x; i <= n ; ++i){
        fscanf(in,"%d", &x);
        val[i - 1] = i;
        urm[i - 1] = lst[x];
        lst[x] = i - 1;
    }

    dfs(1, 1);
    mRmq();

    FILE *out = fopen("lca.out","w");
    for(int i = 1, x, y; i <= m ; i++){
        fscanf(in,"%d%d",&x,&y);
        fprintf(out,"%d\n",lca(x, y));
    }
    fclose(in);
    fclose(out);
    return 0;
}