Cod sursa(job #2881566)

Utilizator ViAlexVisan Alexandru ViAlex Data 30 martie 2022 16:39:42
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.57 kb
#include<iostream>
#include<deque>
#include<algorithm>
#include<fstream>
#include<vector>
using namespace std;

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

const int mx=2e5;

int n,m,num_paths,v[mx],subtree[mx],path_father[mx],node_path[mx],path_depth[mx],node_index[mx];
vector<int> g[mx];
vector<int> path_list[mx];
vector<int> path_tree[mx];

void build_tree(int index, int path_index ,int l,int r){
	if(l==r){
		path_tree[path_index][index]=v[path_list[path_index][l]];
	}
	else{
		int middle=(l+r)/2;
		build_tree(index*2,path_index,l,middle);
		build_tree(index*2+1,path_index,middle+1,r);
		path_tree[path_index][index]=max(path_tree[path_index][index*2],path_tree[path_index][index*2+1]);
	}
}

int query_tree(int index,int path_index,int l,int r,int a,int b){
	if(l>=a && r<=b){
		return path_tree[path_index][index];
	}
	else{
		int middle=(l+r)/2;
		int result=-1;

		if(a<=middle){
			result=max(result,query_tree(index*2,path_index,l,middle,a,b));
		}
		if(b>middle){
			result=max(result,query_tree(index*2+1,path_index,middle+1,r,a,b));
		}
		return result;
	}
}

void update_tree(int index,int path_index,int l,int r,int pos,int value){
	if(l==r){
		path_tree[path_index][index]=value;
	}
	else{
		int middle=(l+r)/2;
		if(pos<=middle){
			update_tree(index*2,path_index,l,middle,pos,value);
		}
		else{
			update_tree(index*2+1,path_index,middle+1,r,pos,value);
		}
		path_tree[path_index][index]=max(path_tree[path_index][index*2],path_tree[path_index][index*2+1]);
	}
}


void build_segment_trees(){
	for(int i=1;i<num_paths;i++){
		path_tree[i].resize(path_list[i].size()*4);
		build_tree(1,i,0,path_list[i].size()-1);
	}
}

int query_tree(int path_index,int l,int r){
	int result= query_tree(1,path_index,0,path_list[path_index].size()-1,l,r);
	return  result;
}

void read(){
	in>>n>>m;

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

	int a,b;
	for(int i=0;i<n-1;i++){
		in>>a>>b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
}

void dfs(int node,int father){
	subtree[node]=1;
	for(int k:g[node]){
		if(k==father)
			continue;
		dfs(k,node);
		subtree[node]+=subtree[k];
	}
}

void heavypath(int node,int father,int& path){
	int current_path=path;

	path_list[current_path].push_back(node);
	node_path[node]=current_path;
	node_index[node]=path_list[current_path].size()-1;
	
	int max_sub_size=-1,best_node=0;

	for(int k:g[node]){
		if(k==father)
			continue;

		if(subtree[k]>max_sub_size){
			max_sub_size=subtree[k];
			best_node=k;
		}
	}
	if(max_sub_size!=-1){
		heavypath(best_node,node,path);
	}

	for(int k:g[node]){
		if(k==father || k==best_node)
			continue;
		path++;
		path_father[path]=node;
		path_depth[path]=path_depth[current_path]+1;
		heavypath(k,node,path);
	}
}

int query(int a,int b){
	int result=0;
	while(node_path[a]!=node_path[b]){
		int path_a=node_path[a],path_b=node_path[b];

		if(path_depth[path_a]>=path_depth[path_b]){
			result=max(result,query_tree(path_a,0,node_index[a]));
			a=path_father[path_a];
		}
		else{
			result=max(result,query_tree(path_b,0,node_index[b]));
			b=path_father[path_b];
		}
	}
	int l=min(node_index[a],node_index[b]);
	int r=max(node_index[a],node_index[b]);

	result=max(result,query_tree(node_path[b],l,r));
	return result;
}

void update(int node,int value){
	int np=node_path[node],ni=node_index[node];
	update_tree(1,np,0,path_list[np].size()-1,ni,value);
}


void solve(){
	dfs(1,0);
	int path_index=1;
	heavypath(1,0,path_index);
	num_paths=path_index+1;
	build_segment_trees();

	int a,b,c;
	for(int i=0;i<m;i++){
		in>>a>>b>>c;
		if(a==1){
			out<<query(b,c)<<'\n';
		}
		else{
			update(b,c);
		}
	}
}

int main(){
	read();
	solve();
	return 0;
}