Cod sursa(job #2768136)

Utilizator andreic06Andrei Calota andreic06 Data 9 august 2021 16:24:25
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.51 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;
const int NMAX = 1e5;
const int MMAX = 2e6;
const int MAX_LOG = 18;
const int ROOT = 1;

vector<int> graf[1 + NMAX];
int height[2 * NMAX], node[2 * NMAX];
int index[1 + NMAX];

int step = 1;
void euler_tour ( int root, int root_height ) {

    ///cout << root << " ";

    height[step] = root_height;
    node[step] = root;
    index[root] = step ++;

    for ( auto adj_node : graf[root] ) {
        euler_tour ( adj_node, root_height + 1 );

        ///cout << root << " ";

        height[step] = root_height;
        node[step] = root;
        index[root] = step ++;
    }

}

int RMQ[2 * NMAX + 1][1 + MAX_LOG];
int LOG_Table[2 * NMAX + 1];
void generate_LogTable () {
    LOG_Table[1] = 0;
    for ( int this_index = 2; this_index <= 2 * NMAX + 1; this_index ++ )
       LOG_Table[this_index] = LOG_Table[this_index / 2] + 1;
}
void generate_RMQ () {

    step --;
    for ( int i = 1; i <= step; i ++ )
       RMQ[i][0] = i;

    for ( int jump = 1; ( 1 << jump ) <= step; jump ++ ) {
       for ( int i = 1; i + ( 1 << jump ) - 1 <= step; i ++ ) {
          int mid_point = i + ( 1 << ( jump - 1 ) );

          int first_half = RMQ[i][jump - 1]; int second_half = RMQ[mid_point][jump - 1];
          if ( height[first_half] < height[second_half] )
            RMQ[i][jump] = first_half;
          else
            RMQ[i][jump] = second_half;
       }
    }
}

int query_RMQ ( int first_node, int second_node ) {
    int first_index = index[first_node];
    int second_index = index[second_node];

    if ( first_index > second_index )
      swap ( first_index, second_index );

    int interval_length = second_index - first_index + 1;
    int rmq_log = LOG_Table[interval_length];

    int first_half = RMQ[first_index][rmq_log];
    int second_half = RMQ[second_index - ( 1 << rmq_log ) + 1][rmq_log];

    if ( height[first_half] < height[second_half] )
      return node[first_half];
    return node[second_half];

}
ifstream fin ( "lca.in" );
ofstream fout ( "lca.out" );
int main()
{
   int n, q; fin >> n >> q;
   for ( int i = 1; i < n; i ++ ) {
      int node; fin >> node;
      graf[node].push_back ( i + 1 );
   }

   euler_tour ( ROOT, 0 );
   generate_LogTable (); generate_RMQ ();

   for ( int i = 1; i <= q; i ++ ) {
      int first_node, second_node; fin >> first_node >> second_node;
      fout << query_RMQ ( first_node, second_node ) << "\n";
   }

    return 0;
}