Cod sursa(job #2416393)

Utilizator Radu_FilipescuFilipescu Radu Radu_Filipescu Data 27 aprilie 2019 14:56:24
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.63 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 100005;

int N, M;
vector <int> Ad[NMAX];

int euler[2 * NMAX], last;
int pos[NMAX], h[NMAX];
int rmq[20][2 * NMAX];
int lg[2 * NMAX];

void Read()
{
  fin >> N >> M;

  int w;
  for( int i = 2; i <= N; ++i )
  {
    fin >> w;

    Ad[i].push_back( w );
    Ad[w].push_back( i );
  }
}

void DfsEuler( int nod, int parent )
{
  ++last;

  if( pos[nod] == 0 )
  {
    pos[nod] = last;
    h[nod] = h[parent] + 1;
  }

  euler[last] = nod;

  int w;
  for( int i = 0; i < Ad[nod].size(); ++i )
  {
    w = Ad[nod][i];

    if( w == parent ) continue;

    DfsEuler( w, nod );

    euler[++last] = nod;
  }
}

void Do()
{
  DfsEuler( 1, 0 );

  for( int i = 1; i <= last; ++i )
    rmq[0][i] = euler[i];

  int A, B;

  for( int I = 1; ( 1 << I ) <= last; ++I )
  {
    for( int i = 1; i + ( 1 << I ) - 1 <= last; ++i )
    {
      A = rmq[I - 1][i];
      B = rmq[I - 1][i + ( 1 << ( I - 1 ))];

      if( h[A] < h[B] ) rmq[I][i] = A;
      else rmq[I][i] = B;
    }
  }

  lg[2] = 1;
  for( int i = 3; i <= last; ++i )
    lg[i] = lg[i / 2] + 1;

  int ans1, ans2;

  for( int i = 1; i <= M; ++i )
  {
    fin >> A >> B;

    if( pos[A] > pos[B] ) swap( A, B );

    int logg = lg[ pos[B] - pos[A] + 1 ];

    ans1 = rmq[logg][ pos[A] ];
    ans2 = rmq[logg][ pos[B] - ( 1 << logg ) + 1 ];

    if( h[ans1] > h[ans2] ) fout << ans2 << '\n';
    else fout << ans1 << '\n';
  }

}

int main()
{
    Read();
    Do();

    return 0;
}