Cod sursa(job #2029286)

Utilizator stoianmihailStoian Mihail stoianmihail Data 29 septembrie 2017 19:49:54
Problema Lowest Common Ancestor Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 1.37 kb
#include <cstdio>
#include <map>

using std::map;

const int MAX_N = 100000;
const int LOG = 18;

int N, M;
int d[MAX_N + 1];
int father[LOG + 1][MAX_N + 1];
map <int, int> lg;

void init() {
  int i;
  for (i = 0; i <= LOG; i++) {
    lg[1 << i] = i;
  }
}

int dfs(int u) {
  if (d[u] == 0) {
    d[u] = dfs(father[0][u]) + 1;
  }
}

void climb(int &u, int level) {
  while (level) {
    u = father[lg[level & -level]][u];
    level &= level - 1;
  }
}

int lca(int u, int v) {
  if (d[u] > d[v]) {
    climb(u, d[u] - d[v]);
  } else {
    climb(v, d[v] - d[u]);
  }

  if (u == v) {
    return u;
  }

  int i;
  for (i = LOG; i >= 0; i--) {
    if (father[i][u] != father[i][v]) {
      u = father[i][u];
      v = father[i][v];
    }
  }
  return father[0][u];
}

int main(void) {
  int i, u, v;
  FILE *f = fopen("lca.in", "r");

  init();

  fscanf(f, "%d %d", &N, &M);
  for (i = 2; i <= N; i++) {
    fscanf(f, "%d", &father[0][i]);
  }

  d[1] = 1;
  for (i = 2; i <= N; i++) {
    dfs(i);
  }

  for (i = 1; i <= LOG; i++) {
    for (u = 1; u <= N; u++) {
      father[i][u] = father[i - 1][father[i - 1][u]];
    }
  }

  freopen("lca.out", "w", stdout);
  while (M) {
    fscanf(f, "%d %d", &u, &v);
    fprintf(stdout, "%d\n", lca(u, v));
    M--;
  }
  fclose(f);
  fclose(stdout);
  return 0;
}