Cod sursa(job #3169531)

Utilizator giotoPopescu Ioan gioto Data 15 noiembrie 2023 11:35:37
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.48 kb
#include <bits/stdc++.h>
using namespace std;

string to_string(const string &s) {
  return '"' + s + '"';
}

string to_string(bool b) {
  return b ? "true" : "false";
}

template <typename A, typename B>
string to_string(const pair<A, B> &p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template <typename T>
string to_string(const T &v) {
  string s = "{";
  bool first = true;
  for (const auto &it : v) {
    if (!first)
      s += ", ";
    else
      first = false;
    s += to_string(it);
  }
  return s += "}";
}

void debug_out() {
  cerr << endl;
}

template <typename T, typename... Args>
void debug_out(const T &first, const Args&... rest) {
  cerr << to_string(first) << " ";
  debug_out(rest...);
}

#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)


namespace LCA {
  ifstream cin("lca.in");
  ofstream cout("lca.out");
  int n;
  int q;
  int k;
  int tmp;
  vector<int> lg;
  vector<int> ap;
  vector<int> h;
  vector<int> euler;
  vector<vector<int>> mn;
  vector<vector<int>> v;

  void read() {
    cin >> n >> q;
    v.resize(n + 1);
    for (int i = 2; i <= n; ++i) {
      int x;
      cin >> x;
      v[x].push_back(i);
    }
  }

  void dfs(int nod = 1, int papa = 0) {
    ap[nod] = tmp;
    euler[tmp++] = nod;
    for (auto it : v[nod]) {
      if (it == papa)
        continue;

      h[it] = h[nod] + 1;
      dfs(it);
      euler[tmp++] = nod;
    }
  }

  int get_min(int x, int y) {
    return (h[x] < h[y]) ? x : y;
  }

  void build() {
    h.resize(n + 1);
    ap.resize(n + 1);
    euler.resize(2 * n - 1);
    tmp = 0;
    h[1] = 0;
    dfs();

    lg.resize(euler.size() + 1);
    lg[0] = 0;
    for (size_t i = 1; i < lg.size(); ++i)
      lg[i] = lg[i >> 1] + 1;
    // maybe alloc this on bss
    mn.resize(euler.size());
    k = int(lg[euler.size()]);
    for (size_t i = 0; i < mn.size(); ++i) {
      mn[i].resize(k + 1);
      mn[i][0] = euler[i];
    }

    for (int j = 1; j <= k; ++j) {
      for (size_t i = 0; i < mn.size(); ++i) {
        mn[i][j] = get_min(mn[i][j - 1], mn[min(i + (1 << (j - 1)), mn.size() - 1)][j - 1]);
      }
    }
  }

  int query(int x, int y) {
    x = ap[x]; y = ap[y];
    int df = y - x + 1;
    return get_min(mn[x][lg[df]], mn[y + 1 - (1 << lg[df])][lg[df]]);
  }
  
  void print_queries() {
    for (int i = 1; i <= q; ++i) {
      int x, y;
      cin >> x >> y;
      cout << query(x, y) << "\n";
    }
  }
}

int main() {
  LCA::read();
  LCA::build();
  LCA::print_queries();
  return 0;
}