Cod sursa(job #2115381)

Utilizator netfreeAndrei Muntean netfree Data 26 ianuarie 2018 17:59:41
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.26 kb
#include <bits/stdc++.h>

using namespace std;

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

const int N_MAX = 500005;

vector<int> vec[N_MAX];
int eu[N_MAX], niv[N_MAX], ne, n, m, a, b, poz[N_MAX];
int dp[30][N_MAX];

void euler(int nod, int nivel){
  eu[++ne] = nod;
  niv[ne] = nivel;
  poz[nod] = ne;
  for(auto v : vec[nod]){
    euler(v, nivel + 1);
    eu[++ne] = nod;
    niv[ne] = nivel;
  }
}

void init(){
  for(int i = 1; i<=ne; ++i)
    dp[0][i] = i;
  for(int power = 1; (1 << power) <= ne; ++power)
    for(int i = 1; i + (1 <<power) - 1 <= ne; ++i)
      if(niv[dp[power-1][i]] < niv[dp[power-1][i + (1<<(power-1))]])
        dp[power][i] = dp[power-1][i];
      else
        dp[power][i] = dp[power-1][i + (1<<(power-1))];
}

int rmq(int lo, int hi){
  int power = log2(hi - lo + 1);
  if(niv[dp[power][lo]] < niv[dp[power][hi - (1 << power) + 1]])
    return dp[power][lo];
  return dp[power][hi - (1 << power) + 1];
}

int query(int a, int b){
  int lo = min(a,b);
  int hi = max(a,b);
  return eu[rmq(lo, hi)];
}

int main(){
  fin >> n >> m;
  for(int i = 2, nr; i<=n; ++i){
    fin >> nr; vec[nr].push_back(i);
  }

  euler(1, 0);
  init();

  while(m--){
    fin >> a >> b;
    fout << query(poz[a],poz[b]) << "\n";
  }
	return 0;
}

//Andrei Muntean, 2018