Cod sursa(job #3162626)

Utilizator moldovan_robert_lolMoldovan Robert moldovan_robert_lol Data 29 octombrie 2023 15:52:01
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.49 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>

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

int gs, q;
std::vector<std::vector<int>> adj_list;
int heavy_edge_child[100005];
bool heavy_edge_parent[100005];
int init_val[100005];
int sz[100005];
int depth[100005];
int label[100005];
int top[100005];
int up[100005][18];
int tree[400005];

void dfs1(int k, int p, int d) {
	up[k][0] = p;
	//std::cout << "1st ancestor of " << k << ": " << up[k][0] << "\n";
	depth[k] = d;
	//std::cout << "Depth of node " << k << ": " << d << "\n";
	sz[k] = 1;

	int max_sz = 0;
	for (const auto& i : adj_list[k]) {
		if (i!=p) {
			dfs1(i,k,d+1);
			sz[k] += sz[i];
			if (sz[i]>max_sz) {
				max_sz = sz[i];
				heavy_edge_child[k] = i;
				heavy_edge_parent[i] = 1;
			}
		}
	}

	//std::cout << "Subtree size of " << k << ": " << sz[k] << "\n";
}

void dfs2(int k, int p, int& timer) {
	label[k] = ++timer;
	if (heavy_edge_child[k]) {
		top[heavy_edge_child[k]] = top[k];
		dfs2(heavy_edge_child[k],k,timer);
	}

	for (const auto& i : adj_list[k]) {
		if (i!=p&&i!=heavy_edge_child[k]) {
			top[i] = i;
			dfs2(i,k,timer);
		}
	}
}

void preprocess_binary_lifting() {
	for (int l = 1; l < 18; l++) {
		for (int i = 1; i <= gs; i++) {
			up[i][l] = up[up[i][l-1]][l-1];
			//std::cout << (1<<l) << "th ancestor of " << i << ": " << up[i][l] << "\n";
		}
	}
}

void seg_build_tree(int node, int l, int r) {
	if (l==r) {
		tree[node] = init_val[label[l]];
		return;
	}

	int m = (l+r)>>1;
	seg_build_tree(node<<1,l,m);
	seg_build_tree(node<<1|1,m+1,r);
	tree[node] = std::max(tree[node<<1],tree[node<<1|1]);
}

void seg_update(int node, int l, int r, int poz, int val) {
	if (l==r) {
		tree[node] = val;
		return;
	}

	int m = (l+r)>>1;
	if (poz<=m) seg_update(node<<1,l,m,poz,val);
	if (poz>m) seg_update(node<<1|1,m+1,r,poz,val);
	tree[node] = std::max(tree[node<<1],tree[node<<1|1]);
}

int seg_query(int node, int l, int r, int st, int fi) {
	if (l>fi||r<st) return -0x3f3f3f3f;
	if (st<=l&&r<=fi) {
		return tree[node];
	}

	int m = (l+r)>>1;
	return std::max(seg_query(node<<1,l,m,st,fi),seg_query(node<<1|1,m+1,r,st,fi));
}

int kth_ancestor(int node, int k) {
	while (k) {
		int lvl = 31-__builtin_clz(k);
		node = up[node][lvl];
		k ^= (1<<lvl);
	}

	return node;
}

int lca(int a, int b) {
	if (depth[a]>depth[b]) {
		std::swap(a,b);
	}

	b = kth_ancestor(b,depth[b]-depth[a]);
	while (a!=b) {
		int lvl = 17;
		while (lvl>0&&up[a][lvl]==up[b][lvl]) {
			--lvl;
		}

		a = up[a][lvl];
		b = up[b][lvl];
	}

	return a;
}

int hld_query(int a, int b) {
	int lca_ = lca(a,b);
	//std::cout << a << " " << b << " " << lca_ << "\n";

	int ret = -0x3f3f3f3f;
	while (depth[a]>=depth[lca_]) {
		//std::cout << depth[a] << " " << depth[lca_] << "\n";
		if (heavy_edge_parent[a]) {
			if (depth[top[a]]>=depth[lca_]) {
				ret = std::max(ret,seg_query(1,1,gs,label[top[a]],label[a]));
				a = up[top[a]][0];
			}
			else {
				ret = std::max(ret,seg_query(1,1,gs,label[kth_ancestor(a,depth[a]-depth[lca_])],label[a]));
				a = up[top[a]][0];
			}
		}
		else {
			ret = std::max(ret,seg_query(1,1,gs,label[a],label[a]));
			a = up[a][0];
		}
	}

	a = b;
	while (depth[a]>=depth[lca_]) {
		//std::cout << depth[a] << " " << depth[lca_] << "\n";
		if (heavy_edge_parent[a]) {
			if (depth[top[a]]>=depth[lca_]) {
				ret = std::max(ret,seg_query(1,1,gs,label[top[a]],label[a]));
				a = up[top[a]][0];
			}
			else {
				ret = std::max(ret,seg_query(1,1,gs,label[kth_ancestor(a,depth[a]-depth[lca_])],label[a]));
				a = up[top[a]][0];
			}
		}
		else {
			ret = std::max(ret,seg_query(1,1,gs,label[a],label[a]));
			a = up[a][0];
		}
	}

	return ret;
}

int main() {
	fin >> gs >> q;
	for (int i = 1; i <= gs; i++) {
		fin >> init_val[i];
	}

	adj_list.resize(gs+1);
	for (int i = 0, a, b; i < gs-1; i++) {
		fin >> a >> b;
		adj_list[a].emplace_back(b);
		adj_list[b].emplace_back(a);
	}

	dfs1(1,0,1);
	preprocess_binary_lifting();
	{ int timer = 0; top[1] = 1; dfs2(1,0,timer); };
	seg_build_tree(1,1,gs);

	/*for (int i = 1; i <= gs; i++) {
		std::cout << i << "'s heavy edge child: " << heavy_edge_child[i] << "\n";
	}
	for (int i = 1; i <= gs; i++) {
		std::cout << "Top of " << i << "'s chain: " << top[i] << "\n";
	}
	for (int i = 1; i <= gs; i++) {
		std::cout << i << "'s label: " << label[i] << "\n";
	}*/

	while (q--) {
		int op, x, y;
		fin >> op >> x >> y;
		if (op==0) {
			seg_update(1,1,gs,label[x],y);
		}
		else {
			fout << hld_query(x,y) << "\n";
		}

		//std::cout << kth_ancestor(x,y) << "\n";
	}
}