Cod sursa(job #1950327)

Utilizator SolcanMihaiSolcan Mihai Andrei SolcanMihai Data 2 aprilie 2017 21:46:24
Problema Lowest Common Ancestor Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <cstdio>
#include <cmath>
#include <vector>

using namespace std;

const int N = 100005;

int n, m;
int tati[N];
vector<int> vecini[N];
vector<pair<int, int> > euler;
int rmq[4 * N][20];
int rmqx[4 * N][20];
int firstAparition[N];
int nr = 0;

void citire()
{
	scanf("%d %d", &n, &m);

	for(int i = 2; i <= n; i++)
	{
		scanf("%d", &tati[i]);
		vecini[tati[i]].push_back(i);
	}

	for(int i = 1; i <= n; i++)
	{
		firstAparition[i] = -1;
	}
}

void dfs(int x, int adancime)
{
	int l = vecini[x].size();

	if(firstAparition[x] == -1)
	{
		firstAparition[x] = nr;
	}

	for(int i = 0; i < l; i++)
	{
		euler.push_back(make_pair(adancime, x));
		nr++;
		dfs(vecini[x][i], adancime + 1);
	}	

	euler.push_back(make_pair(adancime, x));
	nr++;
}

void construireEuler()
{
	dfs(1, 0);
}

void construireRmq()
{
	int l = euler.size();
	int lg = log2(l);

	for(int i = 0; i < l; i++)
	{
		rmq[0][i] = euler[i].first;
		rmqx[0][i] = euler[i].second;
	}

	for(int i = 1; i <= lg; i++)
	{
		for(int j = 0; j < l; j++)
		{
			int val1 = rmq[i - 1][j];
			int valx1 = rmqx[i - 1][j];
			int val2;
			int valx2;

			int poz = j + (1 << (i - 1));

			if(poz < l)
			{
				val2 = rmq[i - 1][poz];
				valx2 = rmqx[i - 1][poz];


				if(val2 < val1)
				{
					val1 = val2;
					valx1 = valx2;
				}
			}

			rmq[i][j] = val1;
			rmqx[i][j] = valx1;
		}
	}

	//for(int i = 0; i <= lg; i++)
	//{
	//	for(int j = 0; j < l; j++)
	//	{
	//		printf("%d ", rmqx[i][j]);
	//	}
	//	printf("\n");
	//}
}

int main()
{
	freopen("lca.in", "r", stdin);
	freopen("lca.out", "w", stdout);

	citire();
	construireEuler();
	construireRmq();

	for(int k = 0; k < m; k++)
	{
		int tmp1, tmp2;	
		scanf("%d %d", &tmp1, &tmp2);

		int poz1 = firstAparition[tmp1];
		int poz2 = firstAparition[tmp2];

		if(poz2 < poz1)
		{
			swap(poz1, poz2);
		}

		int lg = log2(poz2 - poz1 + 1);

		printf("%d\n", max(rmqx[lg][poz1], rmqx[lg][poz2 - (1 << lg) + 1]));
	}

	return 0;
}