Cod sursa(job #2590798)

Utilizator Tudor06MusatTudor Tudor06 Data 28 martie 2020 22:08:43
Problema Lowest Common Ancestor Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.09 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

ifstream fin( "lca.in" );
ofstream fout( "lca.out" );

const int NMAX = 1e5;

vector <int> son[NMAX + 1];
vector <int> euler;
vector <int> level;
int first_apparence[NMAX + 1];
int rmq[20][2 * NMAX];
int log[2 * NMAX];

void read_tree( int n ) {
    for ( int i = 1; i < n; i ++ ) {
        int node;
        fin >> node;
        son[node].push_back( i + 1 );
    }
}
void dfs( int node, int current ) {
    euler.push_back( node );
    level.push_back( current );
    for ( int x : son[node] ) {
        dfs( x, current + 1 );
        euler.push_back( node );
        level.push_back( current );
    }
}
void calc_apparances( int n ) {
    int i;
    for ( i = 1; i <= n; i ++ )
        first_apparence[i] = 2 * n + 1;
    i = 0;
    for ( auto& x : euler ) {
        first_apparence[x] = min( first_apparence[x], i );
        i ++;
    }
}
void calc_log() {
    for ( int i = 2; i < 2 * NMAX; i ++ )
        log[i] = log[i / 2] + 1;
}
void calc_rmq() {
    calc_log();
    for ( int i = 0; i < level.size(); i ++ ) {
        rmq[0][i] = i;
    }
    for ( int l = 1; ( 1 << l ) <= level.size(); l ++ ) {
        for ( int i = 0; i <= level.size() - ( 1 << l ); i ++ ) {
            if ( level[rmq[l - 1][i]] <= level[rmq[l - 1][i + ( 1 << ( l - 1 ) )]] ) {
                rmq[l][i] = rmq[l - 1][i];
            } else {
                rmq[l][i] = rmq[l - 1][i + ( 1 << ( l - 1 ) )];
            }
        }
    }
}
int query( int l, int r ) {
    if ( l > r )
        swap( l, r );
    int lg = log[r - l + 1];
    if ( level[rmq[lg][l]] < level[rmq[lg][r - ( 1 << lg ) + 1]] )
        return euler[level[rmq[lg][l]]];
    else
        return euler[rmq[lg][r - ( 1 << lg ) + 1]];
}
int main() {
    int n, m, i, a, b;
    fin >> n >> m;
    read_tree( n );
    dfs( 1, 0 );
    calc_apparances( n );
    calc_rmq();

    for ( i = 0; i < m; i ++ ) {
        fin >> a >> b;
        fout << query( first_apparence[a], first_apparence[b] ) << '\n';
    }
    return 0;
}