Cod sursa(job #3185841)

Utilizator Xutzu358Ignat Alex Xutzu358 Data 20 decembrie 2023 16:39:25
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.98 kb
#include <fstream>
#include <vector>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");

/// Reprezentarea Euler a unui arbore: de fiecare data cand intram intr-un nod, adaugam perechea
/// {nivel, nod} la reprezentarea euler
/// (si cand intram din tata in fiu, si cand revenim din fiu in tata)
/// LCA-ul dintre doua noduri este nodul cu nivel minim din intervalul dat de primele
/// aparitii ale celor doua noduri in reprezentarea Euler
/// 1. Facem reprezentarea Euler cu un DFS
/// 2. Facem un RMQ pe vectorul cu reprezentarea Euler (se retine perechea minima - se retine practic dupa nivelul minim)
/// 3. Determinam raspunsurile cu un query normal pe RMQ si luam nodul 

int n, m, x, y, l, a, b;
int k[100005], kcurent;
pair < int, int > rmq[200005][25]; /// rmq[n][log n]
vector < int > v[100005];
pair < int, int > euler[200005]; /// 2*n => perechi de tipul {nivel, nod}
int ctr;
int prap[100005]; /// prima aparitie a fiecarui nod in reprezentarea euler

void dfs(int nivel, int nod) {
	euler[++ctr] = { nivel, nod };
	prap[nod] = ctr;
	for (auto newnod : v[nod]) {
		dfs(nivel + 1, newnod);
		euler[++ctr] = { nivel, nod };
	}
}

void create_rmq() {
	/// un rmq pe reprezentarea euler
	for (int j = 0; (1 << j) <= ctr; j++) {
		for (int i = 1; i + (1 << j) - 1 <= ctr; i++) {
			if (j == 0) {
				rmq[i][j] = euler[i];
			}
			else {
				rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
			}
		}
	}
}

void solve() {
	for (int i = 2; i <= ctr; i++) {
		k[i] = k[i - 1];
		if ((1 << (k[i] + 1)) < i) {
			k[i]++;
		}
	}
	for (int t = 1; t <= m; t++) {
		f >> a >> b;
		x = prap[a]; y = prap[b];
		l = y - x + 1; /// lungimea intervalului
		g << min(rmq[x][k[l]], rmq[y-(1<<k[l])+1][k[l]]).second << '\n';
		/// .first = nivelul , .second = nodul
	}
}

int main()
{
	f >> n >> m;
	for (int i = 2; i <= n; i++) {
		f >> x;
		v[x].push_back(i);
	}
	dfs(0, 1); /// radacina = 1 , pe nivelul 0
	create_rmq();
	solve();
}