Pagini recente » Rezultatele filtrării | Rezultatele filtrării | Cod sursa (job #30506) | Rezultatele filtrării | Cod sursa (job #779144)
Cod sursa(job #779144)
// Lca-ul a 2 noduri intr-un arbore este cel mai mic stramos comun.
// Problema se rezolva printr-o parcurgere Euler cu retinerea
// nivelelor fiecarui element parcurs. Astfel minimul va fi
// minimul elementelor de la First[i] la First[j] , First
// reprezentand prima aparitie a elementului i in parcurgerea
// Euler. Cu un RMQ complexitatea va fi O(N lg N+M) in timp
// si memorie. Cu un A-int compexitatea va fi O(N+M lg N) in
// timp si O(N) in memorie.
// Parcurgerea Euler are maxim 4*N elemente.
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;
const int Nmax = 100011 ;
const int LgNx = 20 ;
const int Mmax = 2000011 ;
int N,M,L;
vector< int > V[Nmax];
int Rmq[LgNx][Nmax << 2];
int Lg[Nmax << 1];
int High[Nmax << 1];
int Lvl[Nmax << 1];
int First[Nmax];
ifstream F("lca.in");
ofstream G("lca.out");
void Get( int Nod , int Niv)
{
High[ ++L ]=Nod;
Lvl[ L ]=Niv;
First[ Nod ]=L;
for (int i=0;i<int( V[Nod].size() );++i)
{
Get( V[Nod][i] , Niv+1 );
High[ ++L ]=Nod;
Lvl[ L ]=Niv;
}
}
void Build()
{
for (int i=1;i<=L;++i)
Lg[i]=Lg[i>>1]+1;
for (int i=1;i<=L;++i)
Rmq[0][i]=Lvl[i];
for (int i = 1; (1 << i) < L; ++i)
for (int j = 1; j <= L - (1 << i); ++j)
{
int l = 1 << (i - 1);
Rmq[i][j] = Rmq[i-1][j];
if ( Lvl[Rmq[i-1][j + l]] < Lvl[Rmq[i][j]] )
Rmq[i][j] = Rmq[i-1][j + l];
}
}
int LCA(int x, int y)
{
int Difrence, l, Sol, Sift;
int a = First[x];
int b = First[y];
if (a > b) swap(a, b);
Difrence = b - a + 1;
l = Lg[ Difrence ];
Sol = Rmq[l][a];
Sift = Difrence - (1 << l);
if( Lvl[Sol] > Lvl[Rmq[l][a + Sift]] )
Sol = Rmq[l][a + Sift];
return High[Sol];
}
int main()
{
F>>N>>M;
for (int i=2;i<=N;++i)
{
int x;
F>>x;
V[x].push_back( i );
}
Get( 1,0 );
Build();
while ( M-- )
{
int x,y;
F>>x>>y;
G<<LCA( x,y )<<'\n';
}
}