Cod sursa(job #579290)

Utilizator nautilusCohal Alexandru nautilus Data 12 aprilie 2011 00:12:15
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.81 kb
#include<fstream>
#include<vector>
#define dmax 100010
using namespace std;

int n,m;
vector<int>a[dmax];
int elemeuler;
int euler[2*dmax],nivel[2*dmax],first[dmax];
int logaritm[2*dmax];
int rmq[20][2*dmax];

/*parcurgere euler*/
void parcurgere(int nod, int niv)
{
 int i;
	
 elemeuler++;
 euler[elemeuler] = nod;
 nivel[elemeuler] = niv;
 
 if (first[nod] == 0)
	 first[nod] = elemeuler;
 
 for (i=0; i<(int)a[nod].size(); i++)
	 {
	  parcurgere(a[nod][i], niv+1);
	  elemeuler++;
	  euler[elemeuler] = nod;
	  nivel[elemeuler] = niv;
	 }
}


/*calculez logaritmii*/
void calculare_log()
{
 int i;
 
 for (i=2; i<=elemeuler; i++)
	 logaritm[i] = logaritm[i/2] + 1;
}


/*calculez RMQ*/
void calculare_rmq()
{
 int i,j;
	
 for (i=1; i<=elemeuler; i++)
	 rmq[0][i] = i;
 
 for (i=1; i<=logaritm[elemeuler]; i++)
	 for (j=1; j<=elemeuler-(1<<i)+1; j++)
		 if (nivel[rmq[i-1][j]] < nivel[rmq[i-1][j+(1<<(i-1))]])
			 rmq[i][j] = rmq[i-1][j]; else
			 rmq[i][j] = rmq[i-1][j+(1<<(i-1))];
}


/*calculez LCA*/
int rmqq(int x, int y)
{
 int loga = logaritm[y-x+1];
 
 if (nivel[rmq[loga][x]] < nivel[rmq[loga][y+1-(1<<loga)]])
	 return euler[rmq[loga][x]]; else
	 return euler[rmq[loga][y+1-(1<<loga)]];
}


/*ma pregatesc sa calculez LCA*/
int lca(int x, int y)
{
 int xx,yy;
 
 xx = first[x]; yy = first[y];

 if (xx > yy)
	 swap(xx,yy);
 
 return rmqq(xx,yy);
}


void citire()
{
 int i,x,y;
	
 ifstream fin("lca.in");
 ofstream fout("lca.out");
	
 fin>>n>>m;
 for (i=2; i<=n; i++)
	 {
	  fin>>x;
	  
	  a[x].push_back(i);
	 }
	
 parcurgere(1,0);
 calculare_log();
 calculare_rmq();
 
 for (i=1; i<=m; i++)
	 {
	  fin>>x>>y;
	  
	  fout<<lca(x,y)<<'\n';
	 }
 
 fin.close();
 fout.close();
}


int main()
{
	
 citire();
	
 return 0;
}