Cod sursa(job #3151117)

Utilizator Raul_AArdelean Raul Raul_A Data 19 septembrie 2023 19:50:56
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.73 kb
#include <bits/stdc++.h>
#define cin in
#define cout out
#define eb emplace_back
using namespace std;

const string file_name("heavypath");

ifstream in(file_name + ".in");
ofstream out(file_name + ".out");

const int MAX=1e5;

int n,m,t,x,y,nrL;
int val[MAX+5],w[MAX+5],niv[MAX+5],l[MAX+5],lFather[MAX+5],lNiv[MAX+5],lPozTree[MAX+5],Tree[4*MAX+5];
vector<int> G[MAX+5],L[MAX+5];
bitset<MAX+5> v;

void read()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>val[i];
	
	for(int i=1;i<=n-1;i++)
	{
		cin>>x>>y;
		G[x].eb(y);
		G[y].eb(x);
	}
}

void dfs(int nod)
{
	v[nod]=1;
	w[nod]=1;

	int maxl=-1,frunza=-1;

	for(auto x: G[nod])
	{
		if(v[x]) continue;
		frunza=0;
		niv[x]=niv[nod]+1;
		dfs(x);
		w[nod]+=w[x];

		if(maxl==-1) maxl=x;
		else if(w[maxl]<w[x]) maxl=x;
	}
	if(frunza)
	{
		l[nod]=++nrL;
		L[l[nod]].eb(nod);
		return;
	}
	l[nod]=l[maxl];
	L[l[nod]].eb(nod);

	for(auto x: G[nod])
	{
		if(x==maxl or niv[x]<niv[nod]) continue;
		lFather[l[x]]=nod;
		lNiv[l[x]]=niv[nod];
	}
}

void build(int nod,int l,int r,int decal,int lant)
{
	if(l==r)
		Tree[nod+decal]=val[L[lant][l-1]];
	else
	{
		int m=(l+r)/2;
		build(2*nod,l,m,decal,lant);
		build(2*nod+1,m+1,r,decal,lant);

		Tree[nod+decal]=max(Tree[2*nod+decal],Tree[2*nod+1+decal]);
	}
}

void make_paths()
{
	niv[1]=1;
	dfs(1);

	for(int i=1;i<=nrL;i++)
	{
		reverse(L[i].begin(),L[i].end());

		if(i>1) lPozTree[i]=lPozTree[i-1]+L[i-1].size()*4;/// marchez zona din Tree specifica lantului i

		build(1,1,L[i].size(),lPozTree[i],i);
	}
}

void update(int nod,int l,int r,int poz,int val,int decal)
{
	if(l==r)
		Tree[nod+decal]=val;
	else
	{
		int m=(l+r)/2;

		if(poz<=m) update(2*nod,l,m,poz,val,decal);
		else update(2*nod+1,m+1,r,poz,val,decal);

		Tree[nod+decal]=max(Tree[2*nod+decal],Tree[2*nod+1+decal]);
	}
}

int query(int nod,int l,int r,int a,int b,int decal)
{
	if(a<=l and r<=b)
		return Tree[nod+decal];
	int m=(l+r)/2,ans=INT_MIN;

	if(a<=m) ans=max(ans,query(2*nod,l,m,a,b,decal));
	if(b>m) ans=max(ans,query(2*nod+1,m+1,r,a,b,decal));

	return ans;
}

void solve()
{
	for(int i=1;i<=m;i++)
	{
		cin>>t>>x>>y;
		if(t==0) update(1,1,L[l[x]].size(),niv[x]-lNiv[l[x]],y,lPozTree[l[x]]);
		else
		{
			int ans=INT_MIN;
			while(true)
			{
				if(l[x]==l[y])
				{
					if(niv[x]>niv[y]) swap(x,y);
					ans=max(ans,query(1,1,L[l[x]].size(),niv[x]-lNiv[l[x]],niv[y]-lNiv[l[x]],lPozTree[l[x]]));
					break;
				}
				if(lNiv[l[x]]<lNiv[l[y]])
					swap(x,y);
				
				ans=max(ans,query(1,1,L[l[x]].size(),1,niv[x]-lNiv[l[x]],lPozTree[l[x]]));
				x=lFather[l[x]];
			}
			cout<<ans<<'\n';
		}
	}
}

int main()
{
    read();
	make_paths();
	solve();
    return 0;
}