Cod sursa(job #594303)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 6 iunie 2011 23:26:07
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.18 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

vector <unsigned long> G[100005], EulerianF;
unsigned long N, First[100005], Log2[100005], RMQ[20][200010], Level[100005];
bool V[100005];

void DFS (unsigned long X, unsigned long L)
{
    unsigned long i;
    V[X]=true;
    First[X]=EulerianF.size ()-1;
    EulerianF.push_back (X);
    Level[X]=L;;
    for (i=0; i<G[X].size (); ++i)
    {
        if (V[G[X][i]]==false)
        {
            DFS (G[X][i], L+1);
            EulerianF.push_back (X);
        }
    }
}

inline void BuildEulerianF ()
{
    EulerianF.push_back (0);
    DFS (1, 0);
}

inline unsigned long Min (unsigned long a, unsigned long b)
{
    if (a<b)
    {
        return a;
    }
    return b;
}

inline unsigned long Max (unsigned long a, unsigned long b)
{
    if (a>b)
    {
        return a;
    }
    return b;
}

inline unsigned long MinRMQ (unsigned long a, unsigned long b)
{
    if (Level[a]<Level[b])
    {
        return a;
    }
    return b;
}

void BuildRMQ ()
{
    unsigned long i, j, Putere2, n;
    Log2[1]=0;
    for (i=1; i<EulerianF.size (); ++i)
    {
        RMQ[0][i]=EulerianF[i];
        if (i>1)
        {
            Log2[i]=Log2[i/2]+1;
        }
    }
    for (i=1; i<=Log2[EulerianF.size ()-1]; ++i)
    {
        n=EulerianF.size ()-(1<<i);
        Putere2=(1<<(i-1));
        for (j=1; j<=n; j++)
        {
            RMQ[i][j]=MinRMQ (RMQ[i-1][j], RMQ[i-1][j+Putere2]);
        }
    }
}

inline unsigned long Query (unsigned long a, unsigned long b)
{
    unsigned long D;
    D=b-a-Log2[b-a+1]+1;
    return MinRMQ (RMQ[Log2[b-a-1]][a], RMQ[Log2[b-a-1]][a+D]);
}

int main()
{
    unsigned long QA, QB, M, i, X;
    fin >> N >> M;
    for (i=2; i<=N; ++i)
    {
        fin >> X;
        G[X].push_back (i);
        G[i].push_back (X);
    }
    BuildEulerianF ();
    BuildRMQ ();
    for (; M>0; --M)
    {
        fin >> QA >> QB;
        fout << Query (First[Min (QA, QB)], First[Max (QA, QB)]) << "\n";
    }
    fin.close ();
    fout.close ();
    return 0;
}