Pagini recente » Cod sursa (job #1461119) | Cod sursa (job #1678384) | Cod sursa (job #1916794) | Cod sursa (job #670217) | Cod sursa (job #1042879)
#include <vector>
#include <fstream>
#define Nmax 100099
#define Lmax 20
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
int K,N,M,L[2*Nmax],Euler[2*Nmax],Lg[2*Nmax],First[Nmax],RMQ[Lmax][2*Nmax];
vector < int > Arb[Nmax];
inline void ReadInput()
{
f>>N>>M;
for(int i=2;i<=N;++i)
{
int x;
f>>x;
Arb[x].push_back(i);
}
}
void DFS(int nod, int level)
{
Euler[++K]=nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
L[K]=level; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
First[nod]=K; //se retine si prima aparitie a fiecarui nod in reprezentarea Euler a arborelui
vector < int > :: iterator it;
for(it=Arb[nod].begin();it!=Arb[nod].end();++it)
{
DFS(*it,level+1);
Euler[++K]=nod;
L[K]=level;
}
}
void Make_RMQ()
{
//in Rmq[i][j] va fi nodul de nivel minim
//dintre pozitiile (j, j + 2^i - 1) din reprezentarea Euler a arborelui
for(int i=2;i<=K;++i)Lg[i]=Lg[i>>1]+1;
for(int j=1;j<=K;++j)RMQ[0][j]=j;
for(int i=1;(1<<i)<K;++i)
for(int j=1 ; j<=K-(1<<i) ; ++j)
{
int l=( 1<<(i-1) );
RMQ[i][j] = RMQ[i-1][j];
if( L[ RMQ[i-1][j+l] ] < L[ RMQ[i][j] ]) RMQ[i][j]=RMQ[i-1][j + l];
}
}
int LCA(int x, int y)
{
//LCA-ul nodurilor x si y va fi nodul
//cu nivel minim din secventa (First[x], First[y]) din reprezentarea Euler a arborelui
int diff,l,sol,sh,a=First[x],b=First[y];
if(a>b)swap(a,b);
diff=b-a+1;
l=Lg[diff];
sol=RMQ[l][a];
sh=diff-(1<<l);
if(L[ sol ] > L[ RMQ[l][a + sh] ])sol=RMQ[l][a+sh];
return Euler[sol];
}
int main()
{
ReadInput();
DFS(1,0); // Arbore cu radacina in 1 (radacina are nivel 0)
Make_RMQ();
for(int i=1;i<=M;++i)
{
int x,y;
f>>x>>y;
g<<LCA(x,y)<<'\n';
}
return 0;
}