Cod sursa(job #906282)

Utilizator iulianpopescu13Iulian Popescu iulianpopescu13 Data 6 martie 2013 18:16:52
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.1 kb
# include <fstream>
# include <algorithm>
# include <cmath>
# include <vector>
# define lg2 0.30102999
# define dim 100001
using namespace std;
vector < int > tata( dim ),euler,nivel,poz( dim ),niv( dim );
vector < vector < int > > mat( dim );
int n,m, rmq[ 2 * dim ][ 30 ];
long long nr;
inline void reprezentare_euler( int x )
{
    if( mat[ x ]. size() == 0 )
			euler.push_back( x ), nivel.push_back( niv[ x ] ), poz[ x ] = euler.size()-1;
        else
        {
                euler.push_back( x );
				nivel.push_back( niv[ x ] );
				if( poz[ x ] == 0 )
					poz[ x ] = euler.size()-1;
                for(int i=0; i<mat[ x ]. size(); ++i )
                {
                        niv[ mat[ x ][ i ] ] =  1 + niv[ x ];
                        reprezentare_euler( mat[ x ][ i ] );
                        euler.push_back( x );
						nivel.push_back( niv[ x ] ); 
                }
        }
}
inline void  calculare_rmq()
{
	int nn = nivel.size();
	for(int i=0; i<nn; ++i )
		rmq[ i ][ 0 ] = i;
	for(int j=1; 1<<j <=nn; ++j )
		for(int i=0; i+(1<<j)-1 <nn; ++i)
			if( nivel[ rmq[ i ][ j-1 ] ] < nivel[ rmq[ i + (1<<(j-1)) ][ j-1 ] ] )
				rmq[ i ][ j ] =  rmq[ i ][ j-1 ];
			else
				rmq[ i ][ j ] = rmq[ i + (1<<(j-1)) ][ j-1 ];
}
inline void citire()
{
        ifstream fin("lca.in");
        ofstream fout("lca.out");
        fin >> n >> m;
        for(int i=2; i<=n; ++i )
        {
                fin >> tata[ i ];
                mat[ tata[ i ] ].push_back( i );
        }
		niv[ 1 ] = 0;
        reprezentare_euler( 1 );
		/*for(int i=0; i<euler.size(); ++ i)
			fout << euler[ i ] <<" ";
		fout<<"\n";
		for(int i=1; i<=n; ++ i)
			fout << poz[ i ] <<" ";*/
		calculare_rmq();
        for(; m; --m )
		{
			int x,y;
			fin >> x >> y;
			int i = min( poz[ x ], poz[ y ] );
			int j = max( poz[ x ], poz[ y ] );
			int k = log10( double( j-i+1 ) ) / lg2;
			if( nivel[ rmq[ i ][ k ] ] <= nivel[ rmq[ j-(1<<k)+1 ][ k ] ] )
				fout << euler[ rmq[ i ][ k ] ] <<"\n";
			else
				fout << euler[ rmq[ j-(1<<k)+1 ][ k ] ] <<"\n";
		}
}
int main()
{
	citire();
}