Cod sursa(job #2844825)

Utilizator dorufDoru Floare doruf Data 5 februarie 2022 16:46:42
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.48 kb
#include <bits/stdc++.h>
using namespace std;
using Graph = vector<vector<int>>;

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

const int N = 200000 + 5;
int n, q, parent[N], depth[N], pos[N], m;
int lg[2 * N], rmq[20][2 * N];
vector<int> euler(1);

Graph adj(N);

int minDepth(int x, int y) {
  return (depth[x] < depth[y] ? x : y);
}

void dsfEuler(int u, int dep) {
  euler.emplace_back(u);
  depth[u] = dep + 1;
  pos[u] = (int)euler.size() - 1;
  for (const auto& v : adj[u]) {
    dsfEuler(v, dep + 1);
    euler.emplace_back(u);
  }
}

void buildRmq() {
  lg[1] = 0;
  for (int i = 2; i < 2 * N; ++i)
    lg[i] = lg[i / 2] + 1;
  for (int i = 1; i <= m; ++i)
    rmq[0][i] = euler[i];
  for (int i = 1; i <= lg[m] + 1; ++i) {
    for (int j = 1; j + (1 << (i-1)) <= m; ++j) {
      rmq[i][j] = minDepth(rmq[i - 1][j], rmq[i - 1][j + (1 << (i-1))]);
    }
  }
}

int queryRmq(int l, int r) {
  int k = lg[r - l + 1];
  return minDepth(rmq[k][l], rmq[k][r - (1 << k) + 1]);
}

int lca(int x, int y) {
  return queryRmq(min(pos[x], pos[y]), max(pos[x], pos[y]));
}

int main() {
  ios_base::sync_with_stdio(false);
  fin.tie(nullptr);
  fout.tie(nullptr);

  fin >> n >> q;
  for (int i = 2; i <= n; ++i) {
    int u, w;
    fin >> u ;
    parent[i] = u;
    adj[u].emplace_back(i);
  }
  dsfEuler(1, 0);
  m = euler.size() - 1;
  buildRmq();
  while (q--) {
    int u, v;
    fin >> u >> v;
    fout << lca(u, v) << '\n';
  }
}