Cod sursa(job #1146967)

Utilizator BeilandArnoldArnold Beiland BeilandArnold Data 19 martie 2014 14:30:57
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.93 kb
//O(nlogn+m) reducere la rmq apoi sparse table (ideea de pe tocoder)
#include <fstream>
#include <vector>

class RMQ{
  private:
  	std::vector< std::vector<unsigned> > ST;
  	std::vector< unsigned > l;
  public:
  	RMQ(std::vector<unsigned> lin){
  		l=lin;
		unsigned n=l.size(), temp=n, logn=0;
		while(temp>>=1) ++logn;
		ST.resize(logn+1,std::vector<unsigned>(n));

		for(unsigned i=0;i<n;++i) ST[0][i]=i;

		for(unsigned j=1;j<=logn;++j)
			for(unsigned i=0;i+(1<<j)-1<n;++i)
				if(l[ST[j-1][i]]<l[ST[j-1][i+(1<<(j-1))]]) ST[j][i]=ST[j-1][i];
				else ST[j][i]=ST[j-1][i+(1<<(j-1))];

  	}
	unsigned get(unsigned a, unsigned b){
		unsigned sz=b-a+1, k=0;
		while(sz>>=1) ++k;
		if(l[ST[k][a]]<l[ST[k][b-(1<<k)+1]]) return ST[k][a];
		else return ST[k][b-(1<<k)+1];
	}
};

inline void euler_dfs(std::vector<unsigned> &euler, std::vector<unsigned> &l,
					  std::vector<unsigned> &first, unsigned n, std::istream &fin){
	std::vector< std::vector<unsigned> > Adj(n+1);
	std::vector<unsigned> aind(n+1,0);

	unsigned nreuler=n;
	for(unsigned i=2;i<=n;++i){ unsigned x; fin>>x; Adj[x].push_back(i); ++nreuler; }

	euler.resize(nreuler); l.resize(nreuler); first.resize(n+1,0);
	std::vector<unsigned> niv(n+1);
	unsigned ei=0;

	std::vector<unsigned> st(n);
	st[0]=1; l[0]=0; niv[1]=0;
	int si=0;

	while(si>-1){
		euler[ei]=st[si];
		if(first[st[si]]==0) first[st[si]]=ei;
		l[ei]=niv[st[si]];
		ei++;

		if(aind[st[si]]<Adj[st[si]].size()){
			unsigned nghb=Adj[st[si]][aind[st[si]]++];
			niv[nghb]=niv[st[si]]+1;
			st[++si]=nghb;
		}
		else --si;
	}
	first[1]=0;
}


int main(){
	std::ifstream fin("lca.in");
	std::ofstream fout("lca.out");

	unsigned n,m; fin>>n>>m;

	std::vector<unsigned> euler;
	std::vector<unsigned> l;
	std::vector<unsigned> first;
	euler_dfs(euler,l,first,n,fin);

	RMQ rmql(l);

	for(unsigned i=0;i<m;++i){
		unsigned a,b; fin>>a>>b;
		if(first[a]>first[b]){ unsigned temp=a; a=b; b=temp; }
		fout<<euler[rmql.get(first[a],first[b])]<<'\n';
	}
}