Cod sursa(job #379849)

Utilizator ssergiussSergiu-Ioan Ungur ssergiuss Data 4 ianuarie 2010 11:07:50
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.73 kb
#include <algorithm>
#include <vector>
using namespace std;

#define DIM 100001
#define LOG 21
#define pb push_back
#define sz size()

int n, m, cnt, lg[ 2*DIM ], eul[ 2*DIM ], rng[ 2*DIM ], first[ DIM ], rmq[ LOG ][ 4*DIM ];
vector <int> vec[ DIM ];

void dfs( int nod, int lvl ) {

    unsigned int I;

    eul[ ++cnt ] = nod;
    rng[ cnt ] = lvl;
    first[ nod ] = cnt;
    for( I = 0; I < vec[ nod ].sz; ++I ) {

        dfs( vec[ nod ][ I ], lvl+1 );

        eul[ ++cnt ] = nod;
        rng[ cnt ] = lvl;
    }
}

void build_rmq() {

    int i, j;

    for( i = 2; i <= cnt; ++i )
        lg[ i ] = lg[ i>>1 ] + 1;
    for( i = 1; i <= cnt; ++i )
        rmq[ 0 ][ i ] = i;

    for( i = 1; ( 1<<i ) < cnt; ++i )
        for( j = 1; j <= cnt - ( 1<<i ); ++j ) {

            rmq[ i ][ j ] = rmq[ i-1 ][ j ];
            if( rng[ rmq[ i-1 ][ j + ( 1<<( i-1 ) ) ] ] < rng[ rmq[ i ][ j ] ] )
                rmq[ i ][ j ] = rmq[ i-1 ][ j + ( 1<<( i-1 ) ) ];
        }
}

int lca( int x, int y ) {

    int a, b, l, dif, rez;

    a = first[ x ];
    b = first[ y ];
    if( a > b )
        swap( a, b );
    dif = b-a+1;
    l = lg[ dif ];
    rez = rmq[ l ][ a ];
    if( rng[ rmq[ l ][ b-( 1<<l )+1 ] ] < rng[ rez ] )
        rez = rmq[ l ][ b-( 1<<l )+1 ];

    return eul[ rez ];
}

int main() {

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

    int i, x, y;

    scanf( "%d %d", &n, &m );
    for( i = 2; i <= n; ++i ) {

        scanf( "%d", &x );
        vec[ x ].pb( i );
    }

    dfs( 1, 0 );
    build_rmq();

    for( i = 1; i <= m; ++i ) {

        scanf( "%d %d", &x, &y );
        printf( "%d\n", lca( x, y ) );
    }

    return 0;
}