Cod sursa(job #2027406)

Utilizator vladm98Munteanu Vlad vladm98 Data 26 septembrie 2017 03:18:29
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.25 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");

vector <int> graf[100001];
vector <int> Aint[100001];
vector <int> hpd[100001];
int nivel[100001];
int lanturi;
int where[100001];
int sub[100001];
int father[100001];
int poz[100001];
int val[100001];
void Build_Aint (int node, int st, int dr, int aint)
{
	if (st == dr)
	{
		Aint[aint][node] = val[hpd[aint][st]];
		return;
	}
	int mij = st+dr>>1;
	Build_Aint(node<<1, st, mij, aint);
	Build_Aint(node<<1|1, mij+1, dr, aint);
	Aint[aint][node] = max(Aint[aint][node<<1], Aint[aint][node<<1|1]);
}
int Query (int node, int st, int dr, int a, int b, int aint)
{
	if (a <= st && dr <= b)
		return Aint[aint][node];
	int mij = st+dr>>1;
	int maxst = -1, maxdr = -1;
	if (a <= mij) maxst = Query(node<<1, st, mij, a, b, aint);
	if (mij < b) maxdr = Query(node<<1|1, mij+1, dr, a, b, aint);
	return max(maxst, maxdr);
}
void Build_Hpd (int node, int tata)
{
	father[node] = tata;
	nivel[node] = nivel[tata]+1;
	sub[node] = 1;
	for (auto x:graf[node])
	{
		if (x == tata) continue;
		// cout << "am muchia " << x << " " << node << "\n\n";
		Build_Hpd(x, node);
		sub[node]+=sub[x];
	}
	if (sub[node]==1)
	{
		++lanturi;
		where[node] = lanturi;
		poz[node] = 0;
		hpd[lanturi].push_back (node);
		return ;
	}
	int best = 0;
	for (auto x:graf[node])
	{
		if (x == tata) continue;
		if (sub[x] > sub[best])
			best = x;
	}
	where[node] = where[best];
	hpd[where[node]].push_back(node);
	poz[node] = (int)hpd[where[node]].size()-1;
}
void reverse (int n)
{
	for (int i = 1; i<=lanturi; ++i)
		reverse(hpd[i].begin(), hpd[i].end());
	for (int i = 1; i<=n; ++i)
		poz[i] = (int)hpd[where[i]].size()-1-poz[i];
}
int solveMaxim (int x, int y)
{
	int ans = -3;
	int wx = where[x], wy = where[y];
	if (wx == wy)
	{
		int a = min(poz[x], poz[y]), b = max(poz[x], poz[y]);
		ans = max(ans, Query(1, 0, (int)hpd[wx].size()-1, a, b, wx));
	}
	else
	{
		if (nivel[hpd[wx][0]] < nivel[hpd[wy][0]])
		{
			swap(x, y);
			swap (wx, wy);
		}
		ans = max (ans, Query(1, 0, (int)hpd[wx].size()-1, 0, poz[x], wx));
		ans = max (ans, solveMaxim(father[hpd[wx][0]], y));
	}
	return ans;
}
void Update (int node, int st, int dr, int poz, int val, int aint)
{
	// cout << "Updatez la lantul " << aint << " cu valoare " << val << " la poz " << poz << '\n';
	// cout << st << " " << dr << '\n';
	if (st == dr)
	{
		Aint[aint][node] = val;
		return ;
	}
	int mij = st+dr>>1;
	if (poz <= mij) Update(node<<1, st, mij, poz, val, aint);
	else Update(node<<1|1, mij+1, dr, poz, val, aint);
	Aint[aint][node] = max(Aint[aint][node<<1], Aint[aint][node<<1|1]);

}
int main(int argc, char const *argv[])
{
	int n, m;
	fin >> n >> m;
	for (int i = 1; i<=n; ++i)
		fin >> val[i];
	for (int i = 1; i<n; ++i)
	{
		int x, y;
		fin >> x >> y;
		graf[x].push_back(y);
		graf[y].push_back(x);
	}
	Build_Hpd(1, 0);
	// for (int i = 1; i<=n; ++i) cout << where[i] << " ";
	// return 0;
	reverse(n);
	// return 0;
	for (int i = 1; i<=lanturi; ++i){
		Aint[i].resize ((int)(hpd[i].size()) << 2);
		Build_Aint(1, 0, (int)hpd[i].size()-1, i);
	}
	// return 0;
	for (int i = 1; i<=m; ++i)
	{
		int type, x, y;
		fin >> type >> x >> y;
		if (type)
			fout << solveMaxim(x, y) << '\n';
		else
			Update (1, 0, (int)hpd[where[x]].size()-1, poz[x], y, where[x]);
	}
	return 0;
}