Cod sursa(job #1961056)

Utilizator SolcanMihaiSolcan Mihai Andrei SolcanMihai Data 10 aprilie 2017 21:05:17
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.9 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 firstAparition[N];
int nr = 0;

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

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

	for(int i = 0; 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(0, 0);
}

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

	for(int i = 0; i < l; i++)
	{
		rmq[i][0] = i;
	}

	for(int i = 1; i <= lg; i++)
	{
		for(int j = 0; j < l; j++)
		{
			if(j + (1 << (i - 1)) < l)
	   		{   
				if(euler[rmq[j][i - 1]].first < euler[rmq[j + (1 << (i - 1))][i - 1]].first)
				{
					rmq[j][i] = rmq[j][i - 1];
				}
				else
				{
					rmq[j][i] = rmq[j + (1 << (i - 1))][i - 1];
				}
			}
			else
			{   
				rmq[j][i] = rmq[j][i - 1];
			}
		}
	}
}

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

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

	int l = euler.size();

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

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

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

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

		tmp2 = euler[rmq[poz1][lg]].first;
		int tmp3 = euler[rmq[poz2 - ((1 << lg)) + 1][lg]].first;

		if(tmp2 < tmp3)
		{
			tmp1 = rmq[poz1][lg];
		}
		else
		{
			tmp1 = rmq[poz2 - ((1 << lg)) + 1][lg];	
		}

		printf("%d\n", euler[tmp1].second + 1);
	}

	return 0;
}