Cod sursa(job #2503860)

Utilizator MoodyFaresFares Mohamad MoodyFares Data 3 decembrie 2019 20:53:40
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.58 kb
#include <cstdio>
#include <vector>
#include <algorithm>

const int MAX_N = 100000;

std::vector<int> g[1 + MAX_N];
int rmq[1 + 2 * MAX_N][20];
int euler[1 + 2 * MAX_N], k;
int level[1 + 2 * MAX_N];
int first[1 + MAX_N];

void dfs(int node, int dad, int lev) {
  euler[++k] = node;
  level[k] = lev;
  first[node] = k;
  for (auto u : g[node]) {
    if (u != dad) {
      dfs(u, node, lev + 1);
      euler[++k] = node;
      level[k] = lev;
    }
  }
}

int exp2(int x) {
  int k = -1;
  for (int i = 1; i <= x; i += i) {
    k++;
  }
  return k;
}

int lca(int x, int y) {
  x = first[x];
  y = first[y];
  if (x > y) {
    int aux = x;
    x = y;
    y = aux;
  }
  int lg = exp2(y - x + 1);
  if (level[rmq[x][lg]] < level[rmq[y - (1 << lg) + 1][lg]])
    return euler[rmq[x][lg]];
  else
    return euler[rmq[y - (1 << lg) + 1][lg]];
}

int main() {
  freopen("lca.in", "r", stdin);
  freopen("lca.out", "w", stdout);

  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = 2; i <= n; i++) {
    int x;
    scanf("%d", &x);
    g[x].push_back(i);
    g[i].push_back(x);
  }
  dfs(1, 0, 0);
  for (int i = 1; i <= k; i++) {
    rmq[i][0] = i;
  }
  for (int j = 1; (1 << j) <= k; j++) {
    for (int i = 1; i + (1 << j) - 1 <= k; i++) {
      if (level[rmq[i][j - 1]] < level[rmq[i + (1 << (j - 1))][j - 1]])
        rmq[i][j] = rmq[i][j - 1];
      else
        rmq[i][j] = rmq[i + (1 << (j - 1))][j - 1];
    }
  }
  for (int i = 1; i <= m; i++) {
    int x, y;
    scanf("%d%d", &x, &y);
    printf("%d\n", lca(x, y));
  }
  return 0;
}