Cod sursa(job #2332900)

Utilizator paniniPanayiotis Panayiotou panini Data 31 ianuarie 2019 13:21:29
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.05 kb
// #include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <cmath>
#include <unordered_map>
#define pii pair<int, int>
#define vec vector
#define MAXN 100001
// #define MAXN 100001

using namespace std;

vector<int> map2id(MAXN);
vector<int> id2Vertex(MAXN);
int id = 0;
vector<int> firstOcc(MAXN);
vec<vec<int> > adj(MAXN, vec<int>());
vector<int> a;
vector<int> logOf(MAXN * 2);
vec<vec<int> > rmq(MAXN * 2, vec<int>(60 + 1)); // [from][dist] for 2^dist

void dfs(int v, vector<int>& linearization, vec<vec<int> >& adj) {
  map2id[v] = id;
  id2Vertex[id] = v;
  id++;
  firstOcc[v] = linearization.size();
  linearization.push_back(map2id[v]);
  for (auto neigh: adj[v]) {
    dfs(neigh, linearization, adj);
    linearization.push_back(map2id[v]);
  }
}

void testcase() {
  ifstream cin("lca.in");
  ofstream cout("lca.out");
  int nElems, m;
  cin >> nElems >> m;
  int father;
  for (int i = 1; i <= nElems - 1; i++) {
    cin >> father;
    adj[father - 1].push_back(i);
  }
  dfs(0, a, adj);
  int n = a.size();

  // fast floor log calculation
  logOf[0] = 0;
  logOf[1] = 0;
  for (int i = 2; i <= n; i++) {
    logOf[i] = logOf[i / 2] + 1;
  }

  int biggestPower = logOf[n];
  for (int i = 0; i < n; i++) rmq[i][0] = a[i];

  for (int pow2 = 1; pow2 <= biggestPower; pow2++) {
    for (int from = 0; from < n; from++) {
      rmq[from][pow2] = rmq[from][pow2 - 1];
      int next = from + (1 << (pow2 - 1));
      if (next >= n) break; // adev
      auto candidate = rmq[next][pow2 - 1];
      if (candidate <  rmq[from][pow2]) rmq[from][pow2] = candidate;
    }
  }

  // answer the queries in O(1)
  int from, to;
  for (int i = 0; i < m; i++) {
    cin >> from >> to;
    --from; --to;
    // first Occurence
    from = firstOcc[from];
    to = firstOcc[to];

    int dist = to - from + 1;
    int logDist = logOf[dist];
    cout << id2Vertex[min(rmq[from][logDist], rmq[to - (1 << logDist) + 1][logDist])] + 1 << "\n";
  }
  cin.close();
  cout.close();
}

int main() {
  // ios_base::sync_with_stdio(false);
  // cin.tie(0);
  testcase();
  return 0;
}