Cod sursa(job #1752831)

Utilizator catu_bogdan_99Catu Bogdan catu_bogdan_99 Data 5 septembrie 2016 13:09:55
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.8 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

#define NMAX 100005

vector < int > v[ NMAX ];
int indi;
int euler[ NMAX * 2 ], nivele[ NMAX * 2 ], first[ NMAX ];
int rmq[ 20 ][ NMAX * 2 ], lg[ NMAX * 2 ];

void computeRMQ( );
int LCA( int x, int y );
void computeLCA( int nod, int niv );

int main()
{

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

    int n, m, i, j, x, y, q;

    scanf("%d%d",&n,&m);
    for( i = 2; i <= n; ++i ){
        scanf("%d",&x);
        v[ x ].push_back( i );
    }

    computeLCA( 1, 0 );
    computeRMQ( );
    while( m-- ){
        scanf("%d%d",&x,&y);
        printf("%d\n",LCA( x, y ));
    }


    return 0;

}

void computeRMQ( ){

    int i, j, k;

    for( i = 2; i <= indi; ++i ) lg[ i ] = lg[ i / 2 ] + 1;
    for( i = 1; i <= indi; ++i ) rmq[ 0 ][ i ] = i;

    for( i = 1; ( 1 << i ) < indi; ++i ){
        k = ( 1 << i );
        for( j = 1; j + k <= indi; ++j ){
            rmq[ i ][ j ] = rmq[ i - 1 ][ j + k / 2 ];
            if( nivele[ rmq[ i - 1 ][ j ] ] < nivele[ rmq[ i ][ j ] ] )
                rmq[ i ][ j ] = rmq[ i - 1 ][ j ];
        }
    }


}


int LCA( int x, int y ){

    int a, b, dif;

    x = first[ x ]; y = first[ y ];
    if( x > y ) swap( x, y );

    dif = lg[ y - x + 1 ];
    a = rmq[ dif ][ x ];
    b = rmq[ dif ][ y + 1 - ( 1 << dif ) ];

    if( nivele[ b ] < nivele[ a ] ) a = b;
    return euler[ a ];

}

void computeLCA( int nod, int niv ){

    vector < int > :: iterator it;
    euler[ ++indi ] = nod;  nivele[ indi ] = niv;   first[ nod ] = indi;

    for( it = v[ nod ].begin(); it != v[ nod ].end(); ++it ){
        computeLCA( *it, niv + 1 );
        euler[ ++indi ] = nod;  nivele[ indi ] = niv;
    }

}