Pagini recente » Cod sursa (job #1514040) | Profil Alis15121989 | Cod sursa (job #1327618) | Cod sursa (job #2502969) | Cod sursa (job #1042906)
#include <vector>
#include <fstream>
#define Nmax 100099
#define Lmax 20
using namespace std;
ifstream f("lca.in");
ofstream g("lca.out");
int N,M;
int E[2*Nmax],First[Nmax],Level[2*Nmax]; //parcurgere Euler
int lg[2*Nmax],RMQ[Lmax][2*Nmax]; //RMQ
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 nivel)
{
E[++E[0]]=nod; //nodul actual este adaugat in reprezentarea Euler a arborelui
Level[E[0]]=nivel; //se retine nivelul fiecarei pozitii din reprezentarea Euler a arborelui
First[nod]=E[0]; //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,nivel+1);
E[++E[0]]=nod;
Level[E[0]]=nivel;
}
}
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<=E[0];++i)lg[i]=lg[i/2]+1;
for(int j=1;j<=E[0];++j)RMQ[0][j]=j;
for(int i=1; (1<<i)<=E[0]; ++i)
for(int j=1; j<=E[0]-(1<<i); ++j)
{
int nivel=(1<<(i-1));
RMQ[i][j]=RMQ[i-1][j];
if( Level[ RMQ[i-1][j+nivel] ] < Level[ RMQ[i][j]] ) RMQ[i][j]=RMQ[i-1][j+nivel];
}
}
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 left=First[x],right=First[y];
if(left>right)swap(left,right);
int diff=right-left+1;
int log=lg[diff];
int sol=RMQ[log][left];
int sh=diff-(1<<log);
if(Level[ sol ] > Level[ RMQ[log][left+sh] ])sol=RMQ[log][left+sh];
return E[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;
}