Cod sursa(job #3144175)

Utilizator daristyleBejan Darius-Ramon daristyle Data 5 august 2023 18:03:30
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.74 kb
#include <fstream>

using namespace std;

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

const int N_MAX = 1e5;
const int LOG_MAX = 17;

template<typename T>
class AncestorsSparseTable{
private:
		T table[LOG_MAX][N_MAX + 1];

public:
		void build(int n, ifstream& fin){
			T aux{};
			table[0][1] = aux;
			for(int i = 2; i <= n; ++i){
				fin >> table[0][i];
			}

			for(int e = 1; e < LOG_MAX; ++e)
				for(int i = 1; i <= n; ++i)
					table[e][i] = table[e - 1][table[e - 1][i]];
		}

		T query(int e, int i){
			return table[e][i];
		}

		void print(int n){
			for(int e = 0; e < LOG_MAX; ++e){
				for(int i = 1; i <= n; ++i)
					fout << table[e][i] << ' ';
				fout.put('\n');
			}
		}
};

AncestorsSparseTable<int> ancestors;
int lvl[N_MAX]{};
char lb[N_MAX];

void PrecomputeLog2(int n){
	lb[1] = 0;
	for(int i = 2; i < n; ++i)
		lb[i] = lb[i / 2] + 1;
}

int level(int node){
	if(node <= 1)
		lvl[node] = 0;
	else if(!lvl[node])
		lvl[node] = level(ancestors.query(0, node)) + 1;

	return lvl[node];
}

int LCA(int a, int b){
	if(a == 1 || b == 1)
		int dafw = 4;

	if(level(a) != level(b)){
		if(level(a) > level(b))
			swap(a, b);

		for(int e = lb[level(b) - level(a)]; e >= 0; --e){
			e = e * 2 / 2;
			if(level(a) < level(ancestors.query(e, b)))
				b = ancestors.query(e, b);
		}
		b = ancestors.query(0, b);
	}

	for(int e = lb[level(a)]; e >= 0; --e)
		if(ancestors.query(e, a) != ancestors.query(e, b)){
			a = ancestors.query(e, a);
			b = ancestors.query(e, b);
		}

	if(a != b)
		a = ancestors.query(0, a);

	return a;
}

int main(){
	int n, queries, a, b;
	fin >> n >> queries;

	PrecomputeLog2(n);
	ancestors.build(n, fin);

	for(int i = 0; i < queries; ++i){
		fin >> a >> b;

		fout << LCA(a, b) << '\n';
	}

	fin.close();
	fout.close();
	return 0;
}