Cod sursa(job #2877168)

Utilizator NanuGrancea Alexandru Nanu Data 24 martie 2022 11:07:56
Problema Lowest Common Ancestor Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.04 kb
#include <fstream>
#include <vector>

using namespace std;

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


//Implementare cu Arbori de Intervale ~= 70p;

#define DIM 100000
#define INF (1LL << 30)

int n, m, k, sol, solnod;
int ap[DIM + 1];        //prima aparitie a nodului fiecarui nod in reprezentarea euler;
int Euler[DIM * 2 + 1];
int tree[DIM * 8 + 5];
int nivel[DIM * 2 + 1];
vector <int> G[DIM + 1];

static inline void Build(int st, int dr, int nod) {
  if(st == dr) 
    tree[nod] = st; //retin indicele elementelor;
  else {
    int mid = (st + dr) / 2;
    Build(st, mid, nod * 2);
    Build(mid + 1, dr, nod * 2 + 1);

    if(nivel[tree[nod * 2]] < nivel[tree[nod * 2 + 1]])
      tree[nod] = tree[nod * 2];
    else tree[nod] = tree[nod * 2 + 1]; 
  }
}

static inline void Query(int st, int dr, int nod, int left, int right) {
  int min1 = 0, min2 = 0;
  if(left <= st && dr <= right) {
    if(nivel[tree[nod]] < sol) {
      sol = nivel[tree[nod]];
      solnod = Euler[tree[nod]];
    }
    return;
  }

  int mid = (st + dr) >> 1;
  if(left <= mid)
    Query(st, mid, nod * 2, left, right);
  if(mid < right)
    Query(mid + 1, dr, nod * 2 + 1, left, right);
}

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 int lca(int x, int y) {
  int a = ap[x], b = ap[y];
  if(a > b)
    swap(a, b);

  solnod = sol = INF;
  Query(1, k, 1, a, b);   //caut nivelul minim intre prima aparitie a lui x si y;
  return solnod;
}

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);
  }

  nivel[0] = INF;     //santinela;
  k = 0;              //numarul de noduri din parcurgerea euleriana;
  dfs(1, 0);
  Build(1, k, 1);

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

  return 0;
}