Cod sursa(job #3341533)

Utilizator DariusJohnDarius Dumitrescu DariusJohn Data 19 februarie 2026 21:10:44
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.61 kb
#include <bits/stdc++.h>
#include <fstream>
#include <vector>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
vector<int> euler;
vector<int> first_occurrence;
vector<pair<int, int>> st[20]; // sparse table by Euler tour
vector<vector<int>> adj;
vector<int> depth;
int N;

void dfs(int node, int d) {
  depth[node] = d;
  first_occurrence[node] = euler.size();
  euler.push_back(node);
  for (auto it : adj[node]) {
    dfs(it, d + 1);
    euler.push_back(node); // add node again after child
  }
}

void build_rmq() {
  int L = euler.size();
  for (int i = 0; i < 20; i++)
    st[i].resize(L);
  for (int i = 0; i < L; i++)
    st[0][i] = {depth[euler[i]], euler[i]};

  for (int k = 1; (1 << k) <= L; k++) {
    for (int i = 0; i + (1 << k) <= L; i++) {
      if (st[k - 1][i].first < st[k - 1][i + (1 << (k - 1))].first)
        st[k][i] = st[k - 1][i];
      else
        st[k][i] = st[k - 1][i + (1 << (k - 1))];
    }
  }
}

int query(int L, int R) {
  if (L > R)
    swap(L, R);
  int len = floor(log2(R - L + 1));
  if (st[len][L].first < st[len][R - (1 << len) + 1].first)
    return st[len][L].second;
  else
    return st[len][R - (1 << len) + 1].second;
}

int lca(int u, int v) {
  return query(first_occurrence[u], first_occurrence[v]);
}

int main() {
  int M, root, Q;
  fin >> N >> Q;
  adj.resize(N + 1);
  first_occurrence.resize(N + 1);
  depth.resize(N + 1);

  root = 1;
  for (int i = 2; i <= N; i++) {
    int x;
    fin >> x;
    adj[x].push_back(i);
  }

  dfs(root, 1);
  build_rmq();
  for (int i = 0; i < Q; i++) {
    int L, R;
    fin >> L >> R;
    fout << lca(L, R) << '\n';
  }

  return 0;
}