Cod sursa(job #2877191)

Utilizator NanuGrancea Alexandru Nanu Data 24 martie 2022 11:54:43
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.69 kb
#include <fstream>
#include <vector>
 
using namespace std;
 
ifstream fin("lca.in");
ofstream fout("lca.out");

//Solutie cu Rmq;

#define DIM 100000
#define MAXLG 20
#define INF (1LL << 30)
 
int n, m, k;
int ap[DIM + 1];
int Euler[2 * DIM + 1]; //liniarizarea arborelui;
int nivel[2 * DIM + 1];
int lg[2 * DIM + 1];     //logaritm din fiecare numar;
int Rmq[MAXLG + 1][DIM * 8 + 1];
vector <int> G[DIM + 1];

static inline void dfs(int nod, int lvl) {
  Euler[++k] = nod;
  nivel[k] = lvl;
  ap[nod] = k;
  for(auto e : G[nod]) {
    dfs(e, lvl + 1);

    Euler[++k] = nod;
    nivel[k] = lvl;
  }
}

static inline void RMQ() {
  for(int i = 2; i <= k; i++)
    lg[i] = lg[i / 2] + 1;
  
  for(int i = 1; i <= k; i++)
    Rmq[0][i] = i;      //retin indicii; 

  for(int i = 1; (1 << i) < k; i++)
    for(int j = 1; j <= k - (1 << i); j++) {
      int l = 1LL << (i - 1); //lungimea intervalului;
      
      if(nivel[Rmq[i - 1][j]] < nivel[Rmq[i - 1][j + l]])
        Rmq[i][j] = Rmq[i - 1][j];
      else Rmq[i][j] = Rmq[i - 1][j + l];
    }
}

static inline int lca(int x, int y) {
  int a = ap[x], b = ap[y];
  if(a > b)
    swap(a, b);
  
  int dif = b - a + 1;
  int l = lg[dif];
  int q = dif - (1 << l);
  int nod;

  if(nivel[Rmq[l][a + q]] < nivel[Rmq[l][a]])
    nod = Rmq[l][a + q];
  else nod = Rmq[l][a];

  return Euler[nod];
}

int main() {
  fin.tie(0);
  fout.tie(0);

  fin >> n >> m;
  for(int i = 2; i <= n; i++) {
    int x;
 
    fin >> x;
    G[x].push_back(i);
  }
 
  k = 0;
  dfs(1, 0);
  RMQ();

  int x, y;
  for(int i = 1; i <= m; i++) {
    fin >> x >> y;
    fout << lca(x, y) << '\n';
  }
 
  return 0;
}