Cod sursa(job #2650286)

Utilizator AlexPop28Pop Alex-Nicolae AlexPop28 Data 18 septembrie 2020 08:47:20
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.46 kb
#include <bits/stdc++.h>
#define dbg() cerr <<
#define name(x) (#x) << ": " << (x) << ' ' <<

using namespace std;

void Precalc(int node, vector<int> &par, vector<int> &link,
  vector<int> &depth, const vector<vector<int>> &adj) {

  if (par[node] != -1) {
    int p = par[node];
    int d1 = depth[p] - depth[link[p]];
    int d2 = depth[link[p]] - depth[link[link[p]]];
    if (d1 == d2) {
      link[node] = link[link[p]];    
    } else {
      link[node] = par[node];
    }
  } else {
    par[node] = node;
    link[node] = node;
  }

  for (auto &x : adj[node]) {
    par[x] = node;
    depth[x] = 1 + depth[node];
    Precalc(x, par, link, depth, adj);
  }
}

int main() {
  ifstream cin("lca.in");
  ofstream cout("lca.out");

  int n, q; cin >> n >> q;
  vector<vector<int>> adj(n);
  vector<int> par(n, -1), link(n, -1), depth(n);
  for (int i = 1; i < n; ++i) {
    cin >> par[i]; --par[i];
    adj[par[i]].emplace_back(i);
  }

  Precalc(0, par, link, depth, adj);

  auto LCA = [&](int a, int b) {
    if (depth[a] > depth[b]) swap(a, b);
    while (depth[b] > depth[a]) {
      if (depth[link[b]] >= depth[a]) b = link[b];
      else b = par[b];
    }
    if (a == b) return a;
    assert(depth[a] == depth[b]);
    while (a != b) {
      if (link[a] != link[b]) {
        a = link[a]; b = link[b];
      } else {
        a = par[a]; b = par[b];
      }
    }
    return a;
  };

  while (q--) {
    int a, b; cin >> a >> b; --a, --b;
    cout << 1 + LCA(a, b) << '\n';
  }
}