Cod sursa(job #3185837)

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

/// Arbori de intervale - complexitate O(log n) per query 
/// RMQ - putem folosi cand nu avem update-uri, cand intervalele se pot intersecta fara sa incurce
/// rezultatul si avem O(1) per query, O(n log n) la constructie

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();
}