Cod sursa(job #751649)

Utilizator ChallengeMurtaza Alexandru Challenge Data 26 mai 2012 15:54:14
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.64 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

const char InFile[]="heavypath.in";
const char OutFile[]="heavypath.out";
const int MaxN=100111;
const int AINTSIZE=4*MaxN;

ifstream fin(InFile);
ofstream fout(OutFile);

int N,M,V[MaxN],x,y,lant[MaxN],tata_lant[MaxN],g[MaxN],niv[MaxN],aint[AINTSIZE],lant_offset[MaxN],lant_dim[MaxN];
vector<int> G[MaxN],L[MaxN];

void DFS(int nod)
{
	g[nod]=1;
	int gmax=0;
	for(vector<int>::iterator it=G[nod].begin();it!=G[nod].end();++it)
	{
		int &vcn=*it;
		if(!niv[vcn])
		{
			niv[vcn]=niv[nod]+1;
			DFS(vcn);

			g[nod]+=g[vcn];
			tata_lant[lant[vcn]]=nod;
			if(g[gmax]<g[vcn])
			{
				gmax=vcn;
			}
		}
	}

	if(!gmax)
	{
		lant[nod]=++lant[0];
	}
	else
	{
		lant[nod]=lant[gmax];
	}

	L[lant[nod]].push_back(nod);
}

int AINT_lant=0,update_pos,update_val,AINT_offset,query_st,query_dr,query_sol;

void BuildAINT(int nod, int st, int dr)
{
	if(st==dr)
	{
		aint[nod+AINT_offset]=V[L[AINT_lant][st-1]];
		return;
	}

	int mid=st+((dr-st)>>1);
	int l=nod<<1;
	int r=l+1;
	BuildAINT(l,st,mid);
	BuildAINT(r,mid+1,dr);

	if(aint[l+AINT_offset]>aint[r+AINT_offset])
	{
		aint[nod+AINT_offset]=aint[l+AINT_offset];
	}
	else
	{
		aint[nod+AINT_offset]=aint[r+AINT_offset];
	}
}

void UpdateAINT(int nod, int st, int dr)
{
	if(st==dr)
	{
		aint[nod+AINT_offset]=update_val;
		return;
	}

	int mid=st+((dr-st)>>1);
	int l=nod<<1;
	int r=l+1;
	if(update_pos<=mid)
	{
		UpdateAINT(l,st,mid);
	}
	else
	{
		UpdateAINT(r,mid+1,dr);
	}

	if(aint[l+AINT_offset]>aint[r+AINT_offset])
	{
		aint[nod+AINT_offset]=aint[l+AINT_offset];
	}
	else
	{
		aint[nod+AINT_offset]=aint[r+AINT_offset];
	}
}

void QueryAINT(int nod, int st, int dr)
{
	if(query_st<=st && dr<=query_dr)
	{
		if(query_sol<aint[nod+AINT_offset])
		{
			query_sol=aint[nod+AINT_offset];
		}
		return;
	}

	int mid=st+((dr-st)>>1);
	int l=nod<<1;
	int r=l+1;
	if(query_st<=mid)
	{
		QueryAINT(l,st,mid);
	}
	if(query_dr>mid)
	{
		QueryAINT(r,mid+1,dr);
	}
}

int main()
{
	fin>>N>>M;
	for(register int i=1;i<=N;++i)
	{
		fin>>V[i];
	}
	for(register int i=1;i<N;++i)
	{
		fin>>x>>y;
		G[x].push_back(y);
		G[y].push_back(x);
	}

	niv[1]=1;
	DFS(1);
	tata_lant[lant[1]]=0;

	for(register int i=1;i<=lant[0];++i)
	{
		reverse(L[i].begin(),L[i].end());
		lant_dim[i]=L[i].size();

		lant_offset[i]=lant_offset[i-1]+lant_dim[i-1]*4;

		AINT_lant=i;
		AINT_offset=lant_offset[i];
		BuildAINT(1,1,lant_dim[i]);
	}

	for(register int i=1;i<=M;++i)
	{
		int op;
		fin>>op>>x>>y;
		if(op==0)
		{
			AINT_offset=lant_offset[lant[x]];
			update_pos=niv[x]-niv[tata_lant[lant[x]]];
			update_val=y;
			UpdateAINT(1,1,lant_dim[lant[x]]);
		}
		else
		{
			int sol=0;
			while(1)
			{
				query_sol=0;
				if(lant[x]==lant[y])
				{
					AINT_offset=lant_offset[lant[x]];
					query_st=niv[x]-niv[tata_lant[lant[x]]];
					query_dr=niv[y]-niv[tata_lant[lant[y]]];
					if(query_st>query_dr)
					{
						int aux=query_st;
						query_st=query_dr;
						query_dr=aux;
					}
					QueryAINT(1,1,lant_dim[lant[x]]);
					if(sol<query_sol)
					{
						sol=query_sol;
					}
					break;
				}

				if(niv[tata_lant[lant[x]]]<niv[tata_lant[lant[y]]])
				{
					int aux=x;
					x=y;
					y=aux;
				}

				query_st=1;
				query_dr=niv[x]-niv[tata_lant[lant[x]]];
				AINT_offset=lant_offset[lant[x]];
				QueryAINT(1,1,lant_dim[lant[x]]);
				if(sol<query_sol)
				{
					sol=query_sol;
				}

				x=tata_lant[lant[x]];
			}
			fout<<sol<<"\n";
		}
	}

	fin.close();
	fout.close();
	return 0;
}