Cod sursa(job #2921734)

Utilizator alt_contStefan alt_cont Data 1 septembrie 2022 17:26:42
Problema Lowest Common Ancestor Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.4 kb
#include <fstream>
#include <iostream>
#include <vector>
#define MAX 100010
using namespace std;
int log_cache[MAX];
int pow_cache[25];

int parent[MAX];
vector<int> tree[MAX];
	
int rmq_next[2*MAX][20];
int rmq_prev[2*MAX][20];
	
int log2(int n){
	if(log_cache[n])
		return log_cache[n];
	
	if(n == 1)
		return 0;
	
	int counter = 0;
	while(n != 0){
		n = n >> 1;
		++counter;
	}
	
	return counter - 1;
}	
 
	
int min_2adic(int a, int b){	
	int len = log2(b - a + 1);
	int e = 2 * pow_cache[len];
	if(a % e > b % e || a % e == 0)
		return len + 1;
	else
		return len;
}
 
	
int next_2adic(int n, int k){
	if(n % pow_cache[k])
		return (n / pow_cache[k] + 1) * pow_cache[k];
	else
		return (n / pow_cache[k]) * pow_cache[k];	
}
 
	
int prev_2adic(int n, int k){	
	return (n / pow_cache[k]) * pow_cache[k];
}
 
	
void preprocess(int v[], int n){	
	int next_r, prev_r;
	
	for(int i=1; i <= n; ++i)
		rmq_prev[i][0] = rmq_next[i][0] = v[i];
	
	for(int j=1; j <= log2(n); ++j){
		for(int i=0; i <= n; ++i){
			next_r = next_2adic(i, j - 1);
			if(next_r == next_2adic(i, j))
				rmq_next[i][j] = rmq_next[i][j - 1];
			else
				rmq_next[i][j] = max(rmq_next[i][j - 1], rmq_next[next_r + 1][j - 1]);
	
			prev_r = prev_2adic(i, j - 1);
			if(prev_r == prev_2adic(i, j))
				rmq_prev[i][j] = rmq_prev[i][j - 1];
			else
				rmq_prev[i][j] = max(rmq_prev[i][j - 1], rmq_prev[prev_r - 1][j - 1]);
		}
	}
	
}
 
	
int rmq(int a, int b){
	int k = min_2adic(a, b);
	return max(rmq_next[a][k], rmq_prev[b][k]);
}

int t = 0;
vector<int> ans;
vector<int> idxs(3*MAX);
vector<int> d(3*MAX);

void visit(int i, int depth){

	ans.push_back(i);
	d[i] = depth;
	idxs[i] = t; 
	++t;
	for(auto x: tree[i]){
		visit(x, depth + 1);
		ans.push_back(i);
		++t;
	}
}
 
	
int main(){
	ifstream fin;
	ofstream fout;
	fin.open("lca.in");
	fout.open("lca.out"); 
	int m, n, a, b;
	int v[2*MAX];
	
	fin >> n >> m;
	for(int i = 2; i <= n; ++i){
		fin >> parent[i];
		tree[parent[i]].push_back(i);
	}


	visit(1, 0);

	for(int i = 0; i < m; ++i){
		int a, b;
		fin >> a >> b;
		if(idxs[a] > idxs[b])
			swap(a, b);

		int ia = idxs[a];
		int ib = idxs[b];

		int min_depth = 2*MAX;
		int answer;
		for(int j = ia; j <= ib; ++j){
			if(d[ans[j]] < min_depth){
				min_depth = d[ans[j]];
				answer = ans[j];
			}
		}

		fout << answer << "\n";
	}		

}