Pagini recente » Cod sursa (job #2261204) | Cod sursa (job #2870520) | Cod sursa (job #1921304) | Cod sursa (job #2393501) | Cod sursa (job #1042554)
#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[Nmax<<1],Euler[Nmax<<1],Lg[Nmax<<1],First[Nmax];
int RMQ[Lmax][Nmax<<2];
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 i=1;i<=K;++i)RMQ[0][i]=i;
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];
}
inline void Queery()
{
int x,y;
f>>x>>y;
g<<LCA(x,y)<<'\n';
}
int main()
{
ReadInput();
DFS(1, 0);
Make_RMQ();
for(int i=1;i<=M;++i)Queery();
return 0;
}