Cod sursa(job #2812241)

Utilizator AACthAirinei Andrei Cristian AACth Data 4 decembrie 2021 11:25:02
Problema Lowest Common Ancestor Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.66 kb
#include <bits/stdc++.h>
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
#define cin f
#define cout g

const int Max = 1e5;

int n,m;
vector< int > v[Max];
void read()
{
	f>>n>>m;
	int i;
	for(i=2;i<=n;i++)
	{
		int parent;
		f>>parent;
		v[parent].push_back(i);
	}
}
struct Node{
	int nod;
	int depth;
};
vector < Node > parcurgere;
int lastaparitii[Max];
int firstaparitii[Max];


void dfsEuler(int nod,int depth)
{	
	firstaparitii[nod] = parcurgere.size();
	parcurgere.push_back({nod,depth});
	for(auto child : v[nod])
	{
		dfsEuler(child,depth + 1);
		parcurgere.push_back({nod,depth});
	}
	lastaparitii[nod] = parcurgere.size() - 1;
}
//https://www.infoarena.ro/problema/lca
const int Lmax = 2 * Max;
Node ST[Lmax][21];

Node merge(Node n1, Node n2)
{
	if(n1.depth < n2.depth)
		return n1;
	return n2;
}
void init(vector < Node > v)
{
	int i,j;
	int n = v.size() - 1;
	for(i=0;i<n;i++)
		ST[i][0] = v[i];
	for(j = 1; (1<<j) <= n;j++)
	{
		for(i = 0;i + (1<<j) <= n;i++)
			ST[i][j] = merge(ST[i][j - 1],ST[i + (1<<(j - 1))][j - 1]);
	}
}
int get_lca(int n1,int n2)
{
	//n1 apare inainte de n2 l <= r// 
	int left = min(firstaparitii[n1],firstaparitii[n2]);
	int right = max(lastaparitii[n1],lastaparitii[n2]);
	int k = log2(right - left + 1);
	Node ans = merge(ST[left][k],ST[right - (1<<k) + 1][k]);
	return ans.nod;
}


void precompute()
{
	dfsEuler(1,1);//etapa 1
	//rmq pe parcurgere
	init(parcurgere);
}
void query()	
{
	while(m --)
	{
		int n1,n2;
		f>>n1>>n2;
		cout<<get_lca(n1,n2)<<'\n';
	}
}

int main()
{
    read();
    precompute();
    query();

    return 0;
}