Cod sursa(job #2920130)

Utilizator andrei_C1Andrei Chertes andrei_C1 Data 22 august 2022 13:19:15
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.88 kb
#include <bits/stdc++.h>

using namespace std;

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

const int INF = 1e9;

int n, m, labels = 1;
vector<int> nodeValue, subtreeSize, parent, level, nodeLabel, heavyTour, pos, segTree;
vector<vector<int>> adj;

void dfs(int u = 1, int v = -1, int lev = 1) {
	subtreeSize[u] = 1;
	parent[u] = v;
	level[u] = lev;

	for(const auto &it: adj[u]) if(it != v) {
		dfs(it, u, lev + 1);
		subtreeSize[u] += subtreeSize[it];
	}
}

vector<int> head = {1};

void decomp(int u = 1, int v = -1) {
	nodeLabel[u] = head.size() - 1;
	heavyTour.push_back(u);
	pos[u] = heavyTour.size() - 1;

	int heavyNode = 0;

	for(const auto &it: adj[u]) if(it != v) {
		if(subtreeSize[it] > subtreeSize[heavyNode]) {
			heavyNode = it;
		}
	}

	if(heavyNode) {
		decomp(heavyNode, u);

		for(const auto &it: adj[u]) if(it != v && it != heavyNode) {
			head.push_back(it);
			decomp(it, u);
		}
	}
}

void build() {
	segTree = vector<int> (2 * heavyTour.size() + 1);

	for(int i = (int) heavyTour.size(); i < (int) (heavyTour.size() << 1); i++) {
		segTree[i] = nodeValue[heavyTour[i - heavyTour.size()]];
	}

	for(int i = (int) heavyTour.size() - 1; i >= 1; i--) {
		segTree[i] = max(segTree[(i << 1)], segTree[(i << 1) + 1]);
	}
}

void update(int pos, int newVal) {
	pos += heavyTour.size();
	segTree[pos] = newVal;

	for(int i = (pos >> 1); i >= 1; i >>= 1) {
		segTree[i] = max(segTree[(i << 1)], segTree[(i << 1) + 1]);
	}
}

int query(int a, int b) {
	if(a > b) {
		swap(a, b);
	}

	int ret = -INF;

	for(a += heavyTour.size(), b += heavyTour.size(); a <= b; a >>= 1, b >>= 1) {
		if(a & 1) {
			ret = max(ret, segTree[a++]);
		}

		if((b ^ 1) & 1) {
			ret = max(ret, segTree[b--]);
		}
	}

	return ret;
}

int chainQuery(int u, int v) {
	int ret = -INF;

	while(nodeLabel[u] != nodeLabel[v]) {
		cout << u << " " << v << '\n';

		if(level[head[nodeLabel[u]]] > level[head[nodeLabel[v]]]) {
			ret = max(ret, query(pos[u], pos[head[nodeLabel[u]]]));
			u = parent[head[nodeLabel[u]]];
		} else {
			ret = max(ret, query(pos[v], pos[head[nodeLabel[v]]]));
			v = parent[head[nodeLabel[v]]];
		}
	}

	cout << u << " " << v << "\n\n";

	ret = max(ret, query(pos[u], pos[v]));

	return ret;
}

int main() {
	fin >> n >> m;

	adj = vector<vector<int>> (n + 1);
	nodeValue = subtreeSize = parent = level = nodeLabel = pos = vector<int> (n + 1);

	for(int i = 1; i <= n; i++) {
		fin >> nodeValue[i];
	}

	for(int i = 1; i < n; i++) {
		int u, v;
		fin >> u >> v;

		adj[u].push_back(v);
		adj[v].push_back(u);
	}

	dfs();
	subtreeSize[0] = -INF;
	decomp();

	// for(const auto &it: heavyTour) {
	// 	cout << it << " " << nodeLabel[it] << " " << head[nodeLabel[it]] << '\n';
	// }
	// cout << '\n';

	build();

	for(int i = 1; i <= m; i++) {
		int task, x, y;
		fin >> task >> x >> y;

		if(task == 0) {
			nodeValue[x] = y;
			update(pos[x], nodeValue[x]);
		} else {
			fout << chainQuery(x, y) << '\n';
		}
	}
	return 0;
}