Cod sursa(job #2349749)

Utilizator borcanirobertBorcani Robert borcanirobert Data 20 februarie 2019 18:03:26
Problema Heavy Path Decomposition Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.62 kb
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

using VI = vector<int>;
using ll = long long;
using VL = vector<ll>;
using VVI = vector<VI>;

class ST{
public:
	ST(const VI& val)
	{
		for (N = 1; N < (int)val.size(); N <<= 1);
		
		tree = VI(2*N);
		for (size_t i = 0; i < val.size(); ++i)
			tree[N + i] = val[i];
		
		for (int i = N - 1; i > 0; --i)
			tree[i] = max(tree[2 * i], tree[2 * i + 1]);
	}
	
	void Update(int pos, int val)
	{
		pos += N;
		tree[pos] = val;
		for (pos >>= 1; pos > 0; pos >>= 1)
			tree[pos] = max(tree[pos * 2], tree[pos * 2 + 1]);
	}
	
	int Query(int l, int r)
	{
		l += N, r += N;
		int vmax{0};
		while (l <= r)
		{
			vmax = max(vmax, max(tree[l], tree[r]));
			l = (l + 1) / 2;
			r = (r - 1) / 2;
		}
		
		return vmax;
	}
private:
	VI tree;
	int N;
};

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

int N, M;
VI val;
VVI G;
VVI paths;
VI t, nr, h;
VI pos, pathID;
vector<ST> st;

void ReadData();
void DecomposeTree();
void DFS(int node);
int Query(int n1, int n2);
void Update(int node, int val);

int main()
{
	ReadData();
	DecomposeTree();
	
	int type, x, y;
	while (M--)
	{
		fin >> type >> x >> y;

		if (type == 0)
			Update(x, y);
		else
			fout << Query(x, y) << '\n';
	}
	
	fin.close();
	fout.close();
	return 0;
}

void ReadData()
{
	fin >> N >> M;
	
	h = pathID = nr = t = pos = val = VI(N + 1);
	G = VVI(N + 1);
	for (int i = 1; i <= N; ++i)
		fin >> val[i];
	
	int x, y;
	for (int i = 1; i < N; ++i)
	{
		fin >> x >> y;
		
		G[x].push_back(y);
		G[y].push_back(x);
	}
}

void DecomposeTree()
{
	DFS(1);
	
	for (const VI& path : paths)
	{
		VI pathValues;
		for (const int& node : path)
			pathValues.push_back(val[node]);
		
		st.push_back(ST(pathValues));
	}
}

void DFS(int node)
{
	int son{-1};
	
	nr[node] = 1;
	for (const int& next : G[node])
	{
		if (next == t[node])
			continue;
		t[next] = node;
		DFS(next);
		h[next] = h[node] + 1;
		
		nr[node] += nr[next];
		
		if (son == -1 || nr[son] < nr[next])
			son = next;
	}
	
	if (son == -1)
	{
		pathID[node] = paths.size();
		paths.push_back(VI());
	}
	else
		pathID[node] = pathID[son];
	
	paths[pathID[node]].push_back(node);
	pos[node] = (int)paths[pathID[node]].size() - 1;
}

int Query(int n1, int n2)
{
	if (pathID[n1] == pathID[n2])
	{
		if (pos[n1] > pos[n2])
			swap(n1, n2);

		return st[pathID[n1]].Query(pos[n1], pos[n2]);
	}
	
	if ( h[paths[pathID[n1]].back()] < h[paths[pathID[n2]].back()] )
		swap(n1, n2);
	return max(st[pathID[n1]].Query(pos[n1], (int)paths[pathID[n1]].size() - 1),
			Query(t[paths[pathID[n1]].back()], n2));
}

void Update(int node, int val)
{
	st[pathID[node]].Update(pos[node], val);
}