Cod sursa(job #2009460)

Utilizator eftimie1Alex Efrim eftimie1 Data 9 august 2017 19:53:24
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 2.8 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <stack>
#include <cmath>

#define endl '\n'

using namespace std;

ifstream in("lca.in");
ofstream out("lca.out");

int const nmax = 100000;
int const logmax = 18;

vector<int> g[1 + nmax];

int n, m, root;
int depth[1 + nmax], inv[1 + nmax];
int v[1 + 2 * nmax], nv;

int rmq[1 + 2 * nmax][logmax];
int pow2[logmax];

void eulercircuit() {
  fill(depth + 1, depth + n + 1, -1);

  stack<int> st;
  st.push(root);
  depth[root] = 0;
  while (!st.empty()) {
    int from = st.top();
    v[++nv] = from;
    inv[from] = nv;
    if (0 < g[from].size()) {
      int to = g[from].back();
      if (depth[to] < 0)
        depth[to] = depth[from] + 1;
      st.push(to);
      g[from].pop_back();
    } else {
      st.pop();
    }
  }
}

void computermq() {
  int range = 1, x = 0; //range = 2^x
  pow2[0] = 1;

  int from = 1;
  while (from < nv) {
    if (depth[v[from]] < depth[v[from + 1]])
      rmq[from][0] = from;
    else
      rmq[from][0] = from + 1;
    from++;
  }

  while ((range << 1) < nv) {
    range = (range << 1);
    x++;
    pow2[x] = range;

    from = 1;
    while (from + range <= nv) {
      int i = rmq[from][x - 1];
      int j = rmq[from + range - pow2[x - 1]][x - 1];
//      if (x == 1 && from == 10)
//        cout << "D " << i << " " << j << endl;
      if (depth[v[i]] < depth[v[j]])
        rmq[from][x] = i;
      else
        rmq[from][x] = j;
      from++;
    }
  }

//  cout << rmq[10][0] << " " << rmq[10][1] << " " << rmq[10][2] << endl;

  while ((range << 1) < (nmax << 1)) {
    range = (range << 1);
    x++;
    pow2[x] = range;
  }
}

int computelog(int size) {
  if (size <= 4)
    return 0;
  else if (pow2[logmax - 1] < size)
    return (logmax - 1);
  else {
    int lim1 = 0;
    int lim2 = logmax - 1;
    while (lim1 + 1 < lim2) {
      int mid = ((lim1 + lim2) >> 1);
      if (pow2[mid + 1] + 2 < size)
        lim1 = mid;
      else
        lim2 = mid;
    }
    return lim2;
  }
}

int query(int from, int to) {
  if (from == to)
    return from;
  else {
    if (to < from)
      swap(from, to);
    int log = computelog(to - from + 1);
    int answer = min(rmq[from][log], rmq[to - pow2[log]][log]);
//    cout << from << " & " << to << " with log = " << log << " -> " << v[answer] << endl;
    return v[answer];
  }
}

int main() {
  root = 1;
  in >> n >> m;
  for (int i = 2; i <= n; i++) {
    int dad;
    in >> dad;
    g[dad].push_back(i);
  }

  eulercircuit();
//  for (int i = 1; i <= nv; i++)
//    cout << v[i] << " ";
//  cout << endl;

  computermq();

  for (int i = 1; i <= m; i++) {
    int from, to;
    in >> from >> to;
    out << query(inv[from], inv[to]) << endl;
  }
  return 0;
}