Cod sursa(job #1050354)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 8 decembrie 2013 15:18:55
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.12 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

const int Nmax = 100001;
const int LgMax = 20;

vector <int> G[Nmax];

int Euler[2 * Nmax], E;
int Level[2 * Nmax];
int Representative[Nmax];

int RMQ[LgMax][2 * Nmax];
int log2[2 * Nmax];

int N, Q;

void DFS( int nod, int level )
{
    Euler[ ++E ] = nod;
    Level[ E ] = level;

    for ( auto x: G[nod] )
    {
        DFS( x, level + 1 );

        Euler[ ++E ] = nod;
        Level[ E ] = level;
    }
}

void RangeMinimumQuery()
{
    for ( int i = 1; i <= E; ++i )
            RMQ[0][i] = i;

    for ( int i = 1; ( 1 << i ) <= E; ++i )
            for ( int j = 1; j + ( 1 << i ) - 1 <= E; ++j )
            {
                int p = ( 1 << ( i - 1 ) );

                if ( Level[ RMQ[i - 1][j] ] < Level[ RMQ[i - 1][j + p] ] )
                {
                    RMQ[i][j] = RMQ[i - 1][j];
                }
                else
                {
                    RMQ[i][j] = RMQ[i - 1][j + p];
                }
            }

    for ( int i = 2; i <= E; ++i )
            log2[i] = log2[i / 2] + 1;
}

int LCA( int x, int y )
{
    x = Representative[x];
    y = Representative[y];

    if ( x > y )
    {
        swap( x, y );
    }

    int diff = y - x + 1;
    int k = log2[diff];
    int p = ( 1 << k );
    int sh = diff - p;

    int sol = -1;

    if ( Level[ RMQ[k][x] ] < Level[ RMQ[k][x + sh] ] )
    {
        sol = RMQ[k][x];
    }
    else
    {
        sol = RMQ[k][x + sh];
    }

    return Euler[ sol ];
}

int main()
{
    ifstream f("lca.in");
    ofstream g("lca.out");

    f >> N >> Q;

    for ( int i = 2, a; i <= N; ++i )
    {
        f >> a;

        G[a].push_back( i );
    }

    DFS( 1, 0 );

    for ( int i = 1; i <= 2 * N - 1; ++i )
    {
        if ( Representative[ Euler[i] ] == 0 )
        {
            Representative[ Euler[i] ] = i;
        }
    }

    RangeMinimumQuery();

    for ( int i = 1, a, b; i <= Q; ++i )
    {
        f >> a >> b;

        g << LCA( a, b ) << "\n";
    }

    return 0;
}