Cod sursa(job #3288302)

Utilizator pacelaaaCiurea Pavel pacelaaa Data 21 martie 2025 13:29:34
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.5 kb
#include <bits/stdc++.h>

using namespace std;

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

#define cin fin
#define cout fout
#define FR( a, b ) for( int a = 0; a < b; a ++ )
#define FOR( a, c, b ) for( int a = c;  a < b ; a ++ )
#define PB push_back
#define F first
#define S second

typedef pair<int, int> pii;

const int Nmax = 1e5 + 5;
int cnt = 0;
bool processed[Nmax];
int  adancime[Nmax], prima_aparitie[Nmax], parinte[Nmax], semnificativ[2 * Nmax];
pii rmq[18][2 * Nmax], euler[2 * Nmax];

vector<int> sons[Nmax];

void dfs( int nod ) {
  adancime[nod] = adancime[parinte[nod]] + 1;
  euler[++cnt].F = adancime[nod];
  euler[cnt].S = nod;

  if( prima_aparitie[nod] == 0 )
    prima_aparitie[nod] = cnt;

  FR( i, sons[nod].size() )
    if( !processed[ sons[nod][i] ] )
      dfs( sons[nod][i] );

  processed[nod] = true;
  if( nod != 1 ) {
    euler[++cnt].F = adancime[parinte[nod]];
    euler[cnt].S = parinte[nod];
  }
}

int main()
{
    int n, queries, u, v, l, r;
    cin >> n >> queries;


    FOR( i, 2, n + 1 ) {
      cin >> u;
      parinte[i] = u;
      sons[u].PB( i );
    }

    semnificativ[1] = 0;
    int val_crt = 1, nr_crt = 2, i;

    while( nr_crt < 2 * n + 1 ) {
      i = nr_crt;
      while( i < 2 * nr_crt )
        semnificativ[i++] = val_crt;

      nr_crt *= 2;
      val_crt ++;
    }

    FOR( i, 1, n + 1 )
      cout << semnificativ[i] << " ";
    cout << '\n';

    adancime[0] = -1;
    dfs( 1 );

    FOR( i, 1, 2 * n ) {
      rmq[0][i].F = euler[i].F;
      rmq[0][i].S = euler[i].S;
    }

    for( i = 1; ( 1 << i ) < 2 * n; i ++ ) {
      FOR( j, 1, 2 * n ) {
        int k = ( 1 << (i-1) );
        if( j + k < 2 * n ) {
          if( rmq[i-1][j].F <= rmq[i-1][j + k].F ) {
            rmq[i][j].F = rmq[i-1][j].F;
            rmq[i][j].S = rmq[i-1][j].S;
          } else {
            rmq[i][j].F = rmq[i-1][j + k].F;
            rmq[i][j].S = rmq[i-1][j + k].S;
          }
        }
        else {
          rmq[i][j].F = rmq[i-1][j].F;
          rmq[i][j].S = rmq[i-1][j].S;
        }
      }
    }

    FR( i, queries ) {
      cin >> u >> v;
      l = prima_aparitie[u];
      r = prima_aparitie[v];
      if( l > r )
        swap( l, r );

      int len = semnificativ[r - l + 1];
      if( rmq[len][l].F <= rmq[len][r - (1 << len) + 1 ].F )
        cout << rmq[len][l].S << "\n";
      else
        cout << rmq[len][r - (1 << len) + 1].S << "\n";
    }
    return 0;
}