Cod sursa(job #1367409)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 1 martie 2015 20:52:10
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.7 kb
#include <bits/stdc++.h>

using namespace std;

const int Nmax = 100000 + 1;
const int LgMax = 18;

vector<int> G[Nmax];
int posEuler[Nmax];

int euler[2 * Nmax];
int level[2 * Nmax];
int LOG[2 * Nmax];
int rmq[LgMax][2 * Nmax];

int N, M, E;

void dfs(int nod, int d)
{
    E++;
    euler[E] = nod;
    level[E] = d;

    for (int son: G[nod])
    {
        dfs(son, d + 1);

        E++;
        euler[E] = nod;
        level[E] = d;
    }
}

void build_rmq()
{
    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 )
        LOG[i] = LOG[i / 2] + 1;
}

int lca(int x, int y)
{
    x = posEuler[x];
    y = posEuler[y];

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

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

    if ( level[ rmq[k][x] ] < level[ rmq[k][x + sh] ] )
        return euler[ rmq[k][x] ];
    else
        return euler[ rmq[k][x + sh] ];
}

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

    f >> N >> M;

    for ( int i = 2, a; i <= N; ++i )
    {
        f >> a;
        G[a].push_back( i );
    }

    dfs(1, 0);

    for ( int i = 1; i <= E; ++i )
    {
        if ( posEuler[ euler[i] ] == 0 )
        {
            posEuler[ euler[i] ] = i;
        }
    }

    build_rmq();

    for ( int i = 1, a, b; i <= M; ++i )
    {
        f >> a >> b;
        g << lca( a, b ) << "\n";
    }

    return 0;
}