Cod sursa(job #2444161)

Utilizator ArkinyStoica Alex Arkiny Data 30 iulie 2019 14:26:01
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.35 kb
#include<fstream>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;

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



class segment_tree
{

	int* arb;

	void create(int x,int y,int k, const vector<int> &vec)
	{
		if (x == y)
		{
			arb[k] = vec[x-1];

			return;
		}

		int mid = (x + y) / 2;

		create(x, mid, k * 2, vec);
		create(mid + 1, y, k * 2 + 1, vec);


		arb[k] = max(arb[k * 2], arb[k * 2 + 1]);
	}

public:

	void create(const vector<int> &vec)
	{
		arb = new int[vec.size() * 4];

		create(1, vec.size(), 1, vec);
		
	}

	void update(int el, int x, int y, int val, int k)
	{
		int mid = (x + y) / 2;

		if (x == y && el == y)
		{
			arb[k] = val;
			return;
		}
		else if (el <= mid)
			update(el, x, mid, val, k * 2);
		else
			update(el, mid + 1, y, val, k * 2 + 1);

		arb[k] = max(arb[k * 2], arb[k * 2 + 1]);
	}

	int query(int a, int b, int x, int y, int k)
	{
		int mid = (x + y) / 2, e1 = -1, e2 = -1;

		if (x == a && b == y)
			return arb[k];

		if (a <= mid)
			e1 = query(a, min(b, mid), x, mid, k * 2);

		if (b > mid)
			e2 = query(max(mid + 1, a), b, mid + 1, y, k * 2 + 1);

		return max(e1, e2);
	}
};

vector<int> G[100010];
int val[100010];


class HLD
{

	int levels[100010];
	int subtree_nr[100010];

	int father[100010];
	
	int where[100010];

	pair<int, int> segments[100010];
	

	segment_tree hld_comps[100010];

	vector<int> hld_vec[100010];

	
	int nr_comps;


	void level_subtree_nr(int x, int f, int level, vector<int> G[])
	{
		levels[x] = level;
		subtree_nr[x]++;
		for (int i = 0; i < G[x].size(); ++i)
		{
			if (G[x][i] != f)
			{
				level_subtree_nr(G[x][i], x, level + 1, G);

				subtree_nr[x] += subtree_nr[G[x][i]];
			}
		}
	}

	void form_hld_vec(int x, int f, int nr, vector<int> G[], int val[])
	{
		hld_vec[nr].push_back(val[x]);

		where[x] = nr;

		int ok = 1;

		for (int i = 0; i < G[x].size(); ++i)
		{
			if (G[x][i] != f)
			{
				if (subtree_nr[G[x][i]] > subtree_nr[x] / 2)
				{
					ok = 0;
					form_hld_vec(G[x][i], x, nr, G, val);
				}
				else
				{
					
					nr_comps++;
				

					father[nr_comps] = nr;

					segments[nr_comps].first = levels[G[x][i]];

					form_hld_vec(G[x][i], x, nr_comps, G, val);
				}
			}
		}

		if (ok)
			segments[nr].second = levels[x];
	}


	void form_hld()
	{
		for (int i = 0; i <= nr_comps; ++i)
		{
		
			hld_comps[i].create(hld_vec[i]);

			hld_vec[i].clear();

			hld_vec[i].shrink_to_fit();
		}
	}

public:

	void create(vector<int> G[], int val[])
	{
		level_subtree_nr(1, 0, 0, G);
		form_hld_vec(1, 0, 0, G, val);

		form_hld();
	}


	void update(int x, int v)
	{

		int end = segments[where[x]].second - segments[where[x]].first + 1;

		hld_comps[where[x]].update(levels[x] - segments[where[x]].first + 1, 1, end, v, 1);
	}

	int query(int x, int y)
	{
		int lv_x = levels[x];
		int lv_y = levels[y];

 		int comp_x = where[x];
		int comp_y = where[y];

		auto lv_comp_x = segments[comp_x];
		auto lv_comp_y = segments[comp_y];

		int mx = 0;

		while (comp_x != comp_y)
		{
			if (lv_comp_x <= lv_comp_y)
			{
				mx = max(mx, hld_comps[comp_y].query(1, lv_y - lv_comp_y.first + 1, 1, lv_comp_y.second - lv_comp_y.first + 1, 1));

				lv_y = lv_comp_y.first - 1;
				comp_y = father[comp_y];
			}
			else
			{
				mx = max(mx, hld_comps[comp_x].query(1, lv_x - lv_comp_x.first +1, 1, lv_comp_x.second - lv_comp_x.first + 1, 1));

				lv_x = lv_comp_x.first - 1;
				comp_x = father[comp_x];
			}

		
			
			lv_comp_x = segments[comp_x];
			lv_comp_y = segments[comp_y];
		}

		if (lv_x > lv_y)
			swap(lv_x, lv_y);

		mx = max(mx, hld_comps[comp_x].query(lv_x - lv_comp_x.first + 1, lv_y - lv_comp_y.first +1, 1, lv_comp_x.second - lv_comp_x.first + 1, 1));


		return mx;
	}
};

HLD hld;

int main()
{
	int N, Q;
	in >> N >> Q;

	for (int i = 1; i <= N; ++i)
	{
		int v;
		in >> v;
		
		val[i] = v;
	}
	for (int i = 1; i <= N-1; ++i)
	{
		int x, y;

		in >> x >> y;

		G[x].push_back(y);
		G[y].push_back(x);
	}



	hld.create(G, val);

	for (int i = 1; i <= Q; ++i)
	{
		int t, x, y;
		
		in >> t >> x >> y;

		if (t == 0)
		{
			hld.update(x, y);
		}
		else
		{
			out << hld.query(x, y) << "\n";
		}
	}

	return 0;
}