Cod sursa(job #2874010)

Utilizator justin.stoicaJustin Stoica justin.stoica Data 19 martie 2022 12:29:50
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.15 kb
#include <iostream>
#include <fstream>
#include <vector>
 

const int maxn = 1e5;
const int maxLog = 20 ;
 
typedef std::pair<int, int> PII ;
 
 
std::fstream in ("lca.in", std::ios::in) ;
std::fstream out ("lca.out", std::ios::out) ;
 
std::vector<int> G[1 + maxn] ;
 
int path[1 + 5 * maxn], nodesPath ;
int level[1 + 5 * maxn] ;
int firstApp[1 + 5 * maxn] ;
 
void euler_walk(int node) {
	path[++ nodesPath] = node ;
	firstApp[node] = nodesPath ;
	for (int son : G[node]) {
		level[son] = level[node] + 1 ;
		euler_walk(son) ;
		path[++ nodesPath] = node ;
	}
}
 
namespace RMQ {
PII rmq[1 + maxLog][1 + 5 * maxn] ;
int LOG[1 + 5 * maxn] ;
int putere[1 + maxLog] ;
void precalc(int size) {
	for (int i = 2 ; i <= size ; ++ i) {
		LOG[i] = LOG[i / 2] + 1 ;
	}
	putere[0] = 1 ; putere[1] = 2 ;
	for (int i = 2 ; putere[i - 1] < size ; ++ i) {
		putere[i] = putere[i - 1] * 2 ;
	}
}
void makeRmq(int size) {
	precalc(size) ;
	for (int i = 1 ; i <= size ; ++ i) {
		rmq[0][i] = {level[path[i]], path[i]} ;
	}
	for (int len = 1 ; (1 << len) <= size ; ++ len) {
		for (int poz = 1 ; poz + putere[len] - 1 <= size ; ++ poz) {
			if (rmq[len - 1][poz].first < rmq[len - 1][poz + putere[len - 1]].first) {
				rmq[len][poz] = rmq[len - 1][poz] ;
			} else {
				rmq[len][poz] = rmq[len - 1][poz + putere[len - 1]] ;
			}
		}
	}
}
int query(int left, int right) {
	if (left > right) {
		std::swap(left, right) ;
	}
	int dist(right - left + 1) ;
	int len = putere[LOG[dist]] ;
	if (rmq[LOG[dist]][left].first < rmq[LOG[dist]][right - len + 1].first) {
		return rmq[LOG[dist]][left].second ;
	} else {
		return rmq[LOG[dist]][right - len + 1].second ;
	}
}
}
 
int main() {
	int n, m, x, y ;
	in >> n >> m ;
	for (int i = 1 ; i <= n - 1 ; ++ i) {
		in >> x ;
		G[x].push_back(i + 1) ;
	}
	level[1] = 1 ; euler_walk(1) ;
#if DEBUGP == 1
	debugVS(path, nodesPath) ;
	for (int i = 1 ; i <= nodesPath ; ++ i) {
		std::cerr << level[path[i]] << ' ' ;
	}
	std::cerr << '\n' ;
#endif
	RMQ::makeRmq(nodesPath) ;
	for (int i = 1 ; i <= m ; ++ i) {
		in >> x >> y ;
		out << RMQ::query(firstApp[x], firstApp[y]) << '\n' ;
	}
}