Cod sursa(job #2914338)

Utilizator MarcGrecMarc Grec MarcGrec Data 19 iulie 2022 16:59:41
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.23 kb
#define MAX_N 100000

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

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

struct interval_tree
{
	int count{}, previous{};
	vector<int> data{};

	int get(int node, int left, int right, int qleft, int qright)
	{
		if ((qleft <= left) && (right <= qright))
			return data[node];
		else
		{
			int middle = (left + right) >> 1, max_value = 0;
			if (qleft <= middle)
				max_value = get(node << 1, left, middle, qleft, qright);
			if (qright > middle)
				max_value = max(max_value, get(node << 1 | 1, middle + 1, right, qleft, qright));
			return max_value;
		}
	}

	void set(int node, int left, int right, int index, int value)
	{
		if (left == right)
			data[node] = value;
		else
		{
			int middle = (left + right) >> 1;
			if (index <= middle)
				set(node << 1, left, middle, index, value);
			else
				set(node << 1 | 1, middle + 1, right, index, value);
			data[node] = max(data[node << 1], data[node << 1 | 1]);
		}
	}
};

int n, m, v[MAX_N + 1], l[MAX_N + 1], t[2][MAX_N + 1];
vector<interval_tree> d;
vector<int> g[MAX_N + 1];

int decompose(int node = 1, int previous = 0, int level = 1)
{
	l[node] = level;
	int sum = 1, sum_max = 0, node_max = 0;
	for (int next : g[node])
	{
		if (next != previous)
		{
			int sum_next = decompose(next, node, level + 1);
			sum += sum_next;
			if (sum_max < sum_next)
			{
				sum_max = sum_next;
				node_max = next;
			}
			else
			{
				int log2;
				for (log2 = 0; (1 << log2) < t[1][next]; ++log2);
				d[t[0][next]].count = t[1][next];
				d[t[0][next]].previous = node;
				d[t[0][next]].data = vector<int>(1 << (log2 + 1), 0);
			}
		}
	}
	if (sum == 1)
	{
		t[0][node] = d.size();
		t[1][node] = 1;
		d.push_back(interval_tree());
	}
	else
	{
		t[0][node] = t[0][node_max];
		t[1][node] = t[1][node_max] + 1;
	}
	if (node == 1)
	{
		int log2;
		for (log2 = 0; (1 << log2) <= t[1][node]; ++log2);
		d[t[0][node]].count = t[1][node];
		d[t[0][node]].previous = 0;
		d[t[0][node]].data = vector<int>(1 << (log2 + 1), 0);
		for (int i = 1; i <= n; ++i)
			d[t[0][i]].set(1, 1, d[t[0][i]].count, t[1][i], v[i]);
	}
	return sum;
}

int max_on_path(int x, int y)
{
	int maxx = v[x], maxy = v[y];
	while (t[0][x] != t[0][y])
	{
		if (l[d[t[0][x]].previous] > l[d[t[0][y]].previous])
		{
			maxx = max(maxx, d[t[0][x]].get(1, 1, d[t[0][x]].count, t[1][x], d[t[0][x]].count));
			x = d[t[0][x]].previous;
		}
		else
		{
			maxy = max(maxy, d[t[0][y]].get(1, 1, d[t[0][y]].count, t[1][y], d[t[0][y]].count));
			y = d[t[0][y]].previous;
		}
	}
	if (l[x] < l[y])
		x ^= y ^= x ^= y;
	return max(d[t[0][x]].get(1, 1, d[t[0][x]].count, t[1][x], t[1][y]), max(maxx, maxy));
}

int main()
{
	fin >> n >> m;
	for (int i = 1; i <= n; ++i)
		fin >> v[i];
	for (int i = 1; i < n; ++i)
	{
		int x, y;
		fin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	decompose();
	for (int i = 1; i <= m; ++i)
	{
		int type, x, y;
		fin >> type >> x >> y;
		if (type == 0)
			d[t[0][x]].set(1, 1, d[t[0][x]].count, t[1][x], v[x] = y);
		else
			fout << max_on_path(x, y) << '\n';
	}
	fin.close();
	fout.close();
	return 0;
}