Cod sursa(job #1166263)

Utilizator SebiSebiPirtoaca George Sebastian SebiSebi Data 3 aprilie 2014 13:30:04
Problema Lowest Common Ancestor Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.66 kb
#include<iostream>
#include<fstream>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;

#define NMAX 100001
#define INF 1<<30

vector <int> v[NMAX],path[NMAX];
int viz[NMAX],whatpath[NMAX],whatpoz[NMAX],p[NMAX],w[NMAX],t[NMAX],lev[NMAX],nr,c[NMAX],sol1,sol2;
vector <int> a1[NMAX],a2[NMAX];

void dfs(int nod)
{
	int frunza;
	viz[nod]=1;
	frunza=0;
	w[nod]=1;
	for(vector <int> :: iterator it=v[nod].begin();it!=v[nod].end();it++)
		if(viz[*it]==0) {
			t[*it]=nod;
			lev[*it]=lev[nod]+1;
			dfs(*it);
			w[nod]=w[nod]+w[*it];
			if(frunza==0)
				frunza=*it;
			else if(w[frunza]<w[*it])
				frunza=*it;
		}
	if(frunza==0) {
		nr++;
		path[nr].push_back(nod);
		whatpath[nod]=nr;
	}
	else {
		path[whatpath[frunza]].push_back(nod);
		whatpath[nod]=whatpath[frunza];
	}
}

void build_paths()
{
	int i,j;
	for(i=1;i<=nr;i++) {
		reverse(path[i].begin(),path[i].end());
		a1[i].resize(4*path[i].size()+1);
		a2[i].resize(4*path[i].size()+1);
		for(j=0;j<=4*path[i].size();j++) {
			a1[i][j]=-1;
			a2[i][j]=-1;
		}
		for(vector <int> :: iterator it=path[i].begin();it!=path[i].end();it++)
			whatpoz[*it]=it-path[i].begin();
		p[i]=t[path[i][0]];
	}
}

int LCA(int x, int y)
{
	if(whatpath[x]==whatpath[y]) {
		if(lev[x]<=lev[y])
			return x;
		else return y;
	}
	int p1=p[whatpath[x]];
	int p2=p[whatpath[y]];
	if(lev[p2]<lev[p1] || (lev[p2]==lev[p1] && p2==0)) {
		swap(p1,p2);
		swap(x,y);
	}
	return LCA(x,p2);
}

void update2(int nod, int st, int dr, int poz, int arb, int val)
{
	if(st==dr) {
		if(val==1)
			a2[arb][nod]=st;
		else a2[arb][nod]=-1;
		return;
	}
	int mij;
	mij=(st+dr)/2;
	if(poz<=mij)
		update2(nod*2,st,mij,poz,arb,val);
	else update2(nod*2+1,mij+1,dr,poz,arb,val);
	if(a2[arb][nod*2+1]==-1)
		a2[arb][nod]=a2[arb][nod*2];
	else a2[arb][nod]=a2[arb][nod*2+1];
}

void update1(int nod, int st, int dr, int poz, int arb, int val)
{
	if(st==dr) {
		if(val==1)
			a1[arb][nod]=st;
		else a1[arb][nod]=-1;
		return;
	}
	int mij;
	mij=(st+dr)/2;
	if(poz<=mij)
		update1(nod*2,st,mij,poz,arb,val);
	else update1(nod*2+1,mij+1,dr,poz,arb,val);
	if(a1[arb][nod*2]==-1)
		a1[arb][nod]=a1[arb][nod*2+1];
	else a1[arb][nod]=a1[arb][nod*2];
}

void query2(int nod, int st, int dr, int a, int b, int arb)
{
	if(a<=st && dr<=b) {
		if(sol2==-1 && a2[arb][nod]!=-1)
			sol2=path[arb][a2[arb][nod]];
		return ;
	}
	int mij;
	mij=(st+dr)/2;
	if(mij<b)
		query2(nod*2+1,mij+1,dr,a,b,arb);
	if(a<=mij)
		query2(nod*2,st,mij,a,b,arb);
}

void query1(int nod, int st, int dr, int a, int b, int arb)
{
	if(a<=st && dr<=b) {
		cout<<a1[arb][nod]<<endl;
		if(sol1==-1 && a1[arb][nod]!=-1) 
			sol1=path[arb][a1[arb][nod]];
		return ;
	}
	int mij;
	mij=(st+dr)/2;
	if(a<=mij)
		query1(nod*2,st,mij,a,b,arb);
	if(mij<b)
		query1(nod*2+1,mij+1,dr,a,b,arb);
}

void solve1(int x, int y)
{
	if(whatpath[x]==whatpath[y]) {
		query2(1,0,path[whatpath[x]].size()-1,whatpoz[y],whatpoz[x],whatpath[x]);
		return ;
	}
	query2(1,0,path[whatpath[x]].size()-1,0,whatpoz[x],whatpath[x]);
	solve1(p[whatpath[x]],y);
}

void solve2(int x, int y)
{
	if(whatpath[x]==whatpath[y]) {
		query1(1,0,path[whatpath[x]].size()-1,whatpoz[x],whatpoz[y],whatpath[x]);
		return ;
	}
	query1(1,0,path[whatpath[y]].size()-1,0,whatpoz[y],whatpath[y]);
	solve2(x,p[whatpath[y]]);
}

int main ()
{
	int n,x,y,i,m,op,lca;
	ifstream f("lca.in");
	ofstream g("lca.out");
	f>>n>>m;
	for(i=1;i<=n-1;i++) {
		f>>x;
		v[i+1].push_back(x);
		v[x].push_back(i+1);
	}
	dfs(1);
	build_paths();
	for(i=1;i<=m;i++) {
		f>>x>>y;
		g<<LCA(x,y)<<'\n';
	}
	f.close();
	g.close();
	return 0;
}