Cod sursa(job #2823251)

Utilizator andrei_marciucMarciuc Andrei andrei_marciuc Data 27 decembrie 2021 18:40:10
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.08 kb
#include <stdio.h>
    
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize ("unroll-loops")
 
void swap( int& a, int& b ) {
    a ^= b;
    b ^= a;
    a ^= b;
}

static inline int min( int a, int b ) {
    return ( a <= b ? a : b );
}
 
static inline int max( int a, int b ) {
    return ( a >= b ? a : b );
}
 
static inline int mod( int x ) {
    return x < 0 ? -x : x;
}

#include <vector>
#define MAX 100005

std::vector<int> nod[ MAX ];
std::vector<int> el;
int lev[ MAX ], first[ MAX ];
int rmq[ MAX * 4 ][ 20 ];
int log_2[ MAX * 4 ];
int v[ MAX ];
int n, q;
 
void dfs( int x ) {
    el.push_back( x );
    first[ x ] = el.size() - 1;
    lev[ x ] = lev[ v[ x ] ] + 1;
    for( auto next: nod[ x ] )
        if( next != v[ x ] ) {
            dfs( next );
            el.push_back( x );
        }
}
 
int lca( int x, int y ) {
    int a = first[ x ];
    int b = first[ y ];
    if( a > b ) 
        swap( a, b );

    int lg = log_2[ b - a + 1 ];
    int rez = rmq[ a ][ lg ];
    if( lev[ rmq[ b - ( 1 << lg ) + 1 ][ lg ] ] < lev[ rez ] )
        rez = rmq[ b - ( 1 << lg ) + 1 ][ lg ];

    return rez;
}
 
int main()
{
    FILE *fin = fopen( "lca.in", "r" );
    fscanf( fin, "%d%d", &n, &q );
    for( int i = 2; i <= n; i++ ) {
        fscanf( fin, "%d", &v[ i ] );
        nod[ i ].push_back( v[ i ] );
        nod[ v[ i ] ].push_back( i );
    }

    dfs( 1 );

    log_2[ 1 ] = 0;
    int l = el.size();
    for( int i = 2; i <= l; i++ )
        log_2[ i ] = log_2[ i / 2 ] + 1;
 
    for( int i = 0; i < l; i++ )
        rmq[ i ][ 0 ] = el[ i ];

    for( int j = 1; j <= log_2[ l ]; j++ )
        for( int i = 0; i + ( 1 << j ) <= l; i++ ) {
            rmq[ i ][ j ] = rmq[ i ][ j - 1 ];
            if( lev[ rmq[ i + ( 1 << ( j - 1 ) ) ][ j - 1 ] ] < lev[ rmq[ i ][ j ] ] )
                rmq[ i ][ j ] = rmq[ i + ( 1 << ( j - 1 ) ) ][ j - 1 ];
        }
 
    int x, y;
    FILE *fout = fopen( "lca.out", "w" );
    while( q-- ) {
        fscanf( fin, "%d%d", &x, &y );
        fprintf( fout, "%d\n", lca( x, y ) );
    }
    fclose( fin );
    fclose( fout );
    return 0;
}