Cod sursa(job #2500835)

Utilizator mihai50000Mihai-Cristian Popescu mihai50000 Data 28 noiembrie 2019 19:22:08
Problema Heavy Path Decomposition Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.82 kb
#include <bits/stdc++.h>

using namespace std;

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

struct SegmentTree
{
	vector <int> nod;
	
	SegmentTree (int _n)
	{
		nod.resize(4 * _n + 7, 0);
	}
	
	void update(int pos, int l, int r, int x, int val)
	{
		if(l == r)
		{
			nod[pos] = val;
			return ;
		}
		
		int mid = (l + r) / 2;
		
		if(x <= mid)
			update(pos * 2, l, mid, x, val);
		else
			update(pos * 2 + 1, mid + 1, r, x, val);
		
		nod[pos] = max(nod[pos * 2], nod[pos * 2 + 1]);
	}
	
	int query(int pos, int l, int r, int x, int y)
	{
		if(x <= l && r <= y)
			return nod[pos];
		
		int mid = (l + r) / 2;
		int res = -1;
		
		if(x <= mid) res = max(res, query(pos * 2, l, mid, x, y));
		if(y  > mid) res = max(res, query(pos * 2 + 1, mid + 1, r, x, y));
	
		return res;
	}
};

struct HLD
{
	vector <vector <int> > adj;
	vector <int> depth;
	vector <int> position;
	vector <int> subSize;
	vector <int> parent;
	vector <int> link;
	
	HLD(int n)
	{
		adj.resize(n, vector <int> ());
		depth.resize(n, 0);
		position.resize(n, 0);
		subSize.resize(n, 0);
		parent.resize(n, 0);
		link.resize(n, 0);
	}
	
	void addEdge(int x, int y)
	{
		adj[x].push_back(y);
		adj[y].push_back(x);
	}
	
	void build()
	{
		dfs1(1, -1, 0);
		dfs2(1, 1);
	}
	
	vector <pair <int, int> > getPath(int a, int b)
	{
		vector <pair <int, int> > aux;
		
		while(link[a] != link[b])
		{
			if(depth[link[a]] < depth[link[b]])
				swap(a, b);
			
			aux.push_back({position[link[a]], position[a]});
			a = parent[link[a]];
		}
		
		if(depth[a] < depth[b])
			swap(a, b);
		
		aux.push_back({position[b], position[a]});
		
		return aux;
	}
	
	int dfs1(int nod, int prev, int low)
	{
		depth[nod] = low;
		parent[nod] = prev;
		subSize[nod] = 1;
		
		if(prev != -1)
			adj[nod].erase(find(adj[nod].begin(), adj[nod].end(), prev));
		
		for(auto i : adj[nod])
			subSize[nod] += dfs1(i, nod, low + 1);
		
		return subSize[nod];
	}
	
	int timer = 0;
	
	void dfs2(int nod, int to)
	{
		link[nod] = to;
		position[nod] = timer++;
		
		if(adj[nod].size() == 0)
			return ;
		
		pair <int, int> best = {-1, -1};
		
		for(auto i : adj[nod])
			best = max(best, {subSize[i], i});
		
		dfs2(best.second, to);
		
		for(auto i : adj[nod])
			if(i != best.second)
				dfs2(i, i);
	}
};

main()
{
	int n, m;
	fin >> n >> m;
	
	SegmentTree arb(n + 1);
	HLD graf(n + 1);
	
	vector <int> val(n);

	for(auto &i : val)
		fin >> i;
	
	for(int i = 1; i < n; i++)
	{
		int x, y;
		fin >> x >> y;
		
		graf.addEdge(x, y);
	}
	
	graf.build();
	
	for(int i = 1; i <= n; i++)
		arb.update(1, 1, n, graf.position[i], val[i - 1]);
	
	while(m--)
	{
		int t, x, y;
		fin >> t >> x >> y;
		
		if(t == 0)
		{
			arb.update(1, 1, n, graf.position[x], y);
		}
		else
		{
			int res = 0;
			
			for(auto i : graf.getPath(x, y))
			{
				res = max(res, arb.query(1, 1, n, i.first, i.second));
			}
			
			fout << res << '\n';
		}
	}
}