Cod sursa(job #3288186)

Utilizator AndreiMLCChesauan Andrei AndreiMLC Data 20 martie 2025 19:55:09
Problema Lowest Common Ancestor Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.63 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>

using namespace std;

ifstream f("lca.in");
ofstream g("lca.out");

const int NMAX = 100005;
const int LOGMAX = 20;

map<pair<int, int>, int> queries;
int n, m;
vector<int> graph[NMAX];
int parent[NMAX];
int adj[NMAX];
int viz[NMAX];
int stram[NMAX];

int adanc[NMAX];
int rpm[LOGMAX][NMAX];
int depth[NMAX];


/*
int find(int x) {
	if (parent[x] != x) {
		parent[x] = find(parent[x]);
	}
	return parent[x];
}

void unionSet(int x, int y) {
	int rootX = find(x);
	int rootY = find(y);
	if (rootX != rootY) {
		parent[rootY] = rootX;
	}
}

void tarjan(int nod)
{
	viz[nod] = 1;
	stram[nod] = nod;

	for (int v : graph[nod])
	{
		if (!viz[v])
		{
			tarjan(v);
			unionSet(nod, v);
			stram[find(nod)] = nod;
		}
	}

	for (auto it : queries)
	{
		if (it.first.first == nod && viz[it.first.second])
		{
			queries[it.first] = stram[find(it.first.second)];
		}
		else if (it.first.second == nod && viz[it.first.first])
		{
			queries[it.first] = stram[find(it.first.first)];
		}
	}
}*/

void preproces(int a)
{
	for (int i = 1; i < LOGMAX; i++)
	{
		for (int j = 1; j <= a; j++)
		{
			if (rpm[i - 1][j])
			{
				rpm[i][j] = rpm[i - 1][rpm[i - 1][j]];
			}
		}
	}
}

int LCA(int u, int v)
{
	if (depth[u] < depth[v])
	{
		swap(u, v);
	}

	for (int i = LOGMAX - 1; i >= 0; i--)
	{
		if (depth[u] - (1 << i) >= depth[v])
		{
			u = rpm[i][u];
		}
	}

	if (u == v)
	{
		return u;
	}

	for(int i = LOGMAX - 1; i >= 0; i--)
	{
		if(rpm[i][u] && rpm[i][u] != rpm[i][v])
		{
			u = rpm[i][u];
			v = rpm[i][v];
		}
	}

	return rpm[0][u];
}

int main()
{
	/*
	f >> n >> m;
	parent[1] = 1;
	for (int i = 2; i <= n; i++)
	{
		f >> adj[i];
		graph[adj[i]].push_back(i);
		graph[i].push_back(adj[i]);

		parent[i] = i;
	}
	for (int i = 1; i <= m; i++)
	{
		int x, y;
		f >> x >> y;
		queries[{x, y}] = 0;
	}
	tarjan(1);

	for(auto it = queries.crbegin(); it != queries.crend() ;it++)
	{
		g << it -> second << '\n';
	}*/
	
	f >> n >> m;
	for (int i = 2; i <= n; i++)
	{
		f >> adj[i];
		graph[adj[i]].push_back(i);
		graph[i].push_back(adj[i]);
		rpm[0][i] = adj[i];
	}

	queue<int> q;
	q.push(1);
	depth[1] = 1;

	while (!q.empty())
	{
		int vf = q.front();
		q.pop();

		for (auto it : graph[vf])
		{
			if (depth[it] == 0)
			{
				depth[it] = depth[vf] + 1;
				q.push(it);
			}
		}
	}

	preproces(n);

	for (int i = 1; i <= m; i++)
	{
		int x, y;
		f >> x >> y;
		g << LCA(x, y) << '\n';
	}
	return 0;
}