Pagini recente » Cod sursa (job #2831052) | Cod sursa (job #973100) | Cod sursa (job #2766948) | Cod sursa (job #1822246) | Cod sursa (job #1984085)
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
using namespace std;
ifstream fin("lca.in");
ofstream fout("lca.out");
const int MAXN = 100005;
const int MAXLOG = 19;
int N, M;
int t[MAXN];
int lv[MAXN];
int P[MAXN][MAXLOG];
int L[MAXN];
void Read();
void Precalculate();
void AnswerQuery( int x, int y );
int Level( int node );
int main()
{
Read();
Precalculate();
int x, y;
while ( M-- )
{
fin >> x >> y;
AnswerQuery(x, y);
}
fin.close();
fout.close();
return 0;
}
void Read()
{ // citesc sirul tatilor
fin >> N >> M;
for ( int i = 2; i <= N; ++i )
fin >> t[i];
}
void Precalculate()
{
int i, j;
memset(P, -1, sizeof(P));
// P[i][0] este stramosul direct (tatal) lui i defapt
for ( i = 2; i <= N; ++i )
P[i][0] = t[i];
// restul se calculeaza cu ajutorul relatiei de recurenta
for ( j = 1; (1 << j) < N; ++j )
for ( i = 1; i <= N; ++i )
if ( P[i][j - 1] != -1 )
P[i][j] = P[P[i][j - 1]][j - 1];
}
void AnswerQuery( int x, int y )
{
// nodul y trebuie sa fie cel mai indepartat de radacina
if ( Level(x) > Level(y) )
swap(x, y);
// caut log in baza 2 din nivelul la care se afla nodul
// cel mai indepartat de radacina, adica nodul y
int log;
for ( log = 1; (1 << log) <= Level(y); ++log );
--log;
// aduc nodurile la acelasi nivel
for ( int i = log; i >= 0; --i )
if ( Level(P[y][i]) >= Level(x) )
y = P[y][i];
if ( x == y )
{
fout << x << '\n';
return;
}
// caut stramosul lor comun
for ( int i = log; i >= 0; --i )
if ( P[y][i] != -1 && P[y][i] != P[x][i] )
x = P[y][i], y = P[x][i];
fout << t[x] << '\n';
}
int Level( int node ) // determin la ce nivel se afla nodul node
{
if ( node == -1 )
return -1;
if ( node == 1 )
return 1;
int& a = L[node];
if ( a == 0 )
return a = 1 + Level(t[node]);
return a;
}