Cod sursa(job #3289594)

Utilizator AsandeiStefanAsandei Stefan-Alexandru AsandeiStefan Data 27 martie 2025 16:24:39
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.34 kb
#include <fstream>

using namespace std;

const int nmax = 1e5;
const int lmax = 17;

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

int n, m, l, u, v, dp[lmax + 1][nmax + 1], depth[nmax + 1];

int lca(int u, int v) {
  if (depth[u] < depth[v])
    swap(u, v);

  // ridicam u la aceeasi inaltime ca v
  for (int p = l - 1; p >= 0; p--) {
    if (depth[u] - (1 << p) >= depth[v]) {
      u = dp[p][u];
    }
  }

  if (u == v)
    return u;

  // ridicam u si v in paralel pana ajung imediat sub lca
  for (int p = l - 1; p >= 0; p--) {
    if (dp[p][u] != 0 && dp[p][u] != dp[p][v]) {
      u = dp[p][u];
      v = dp[p][v];
    }
  }

  // parintele lor comun este lca
  return dp[0][v];
}

void precalc() {
  while ((1 << l) <= n)
    l++;

  for (int i = 1; i < l; i++) {
    for (int j = 1; j <= n; j++) {
      int prv = dp[i - 1][j];
      if (prv != 0)
        dp[i][j] = dp[i - 1][prv];
    }
  }
}

int calc_depth(int node) {
  if (depth[node] != 0 || node == 1)
    return depth[node];
  return depth[node] = 1 + calc_depth(dp[0][node]);
}

int main() {
  fin >> n >> m;
  for (int i = 2; i <= n; i++)
    fin >> dp[0][i];

  for (int i = 1; i <= n; i++)
    depth[i] = calc_depth(i);
  precalc();

  while (m--) {
    fin >> u >> v;
    fout << lca(u, v) << '\n';
  }
  return 0;
}