Cod sursa(job #2586244)

Utilizator CyborgSquirrelJardan Andrei CyborgSquirrel Data 20 martie 2020 09:09:31
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.44 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

//minecraftminecraft

const int N = 100041;

int n, m;
int val[N];
vector<int> gra[N];
void readtree(){
	fin >> n >> m;
	for(int i = 1; i <= n; ++i){
		fin >> val[i];
	}
	for(int i = 1; i < n; ++i){
		int a, b;
		fin >> a >> b;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}
}

int lv[N], wt[N], dad[N];
void defeseu(int a=1){
	wt[a] = 1;
	for(auto b : gra[a]){
		if(wt[b] == 0){
			dad[b] = a;
			lv[b] = lv[a]+1;
			defeseu(b);
			wt[a] += wt[b];
		}
	}
}

int cid = 1;
int id[N], bs[N];
vector<int> ido;
void decompose(int a=1, int cbs=1){
	bs[a] = cbs;
	id[a] = cid++;
	ido.push_back(a);
	int maxi = -1;
	for(auto b : gra[a]){
		if(wt[b] < wt[a] && (maxi == -1 || wt[b] > wt[maxi])){
			maxi = b;
		}
	}
	
	if(maxi != -1){
		decompose(maxi, cbs);
	}
	for(auto b : gra[a]){
		if(wt[b] < wt[a] && b != maxi){
			decompose(b, b);
		}
	}
}

int tre[N*4];
void update(int p, int v, int tp=1, int lt=1, int rt=n){
	if(lt == rt){
		tre[tp] = v;
	}else{
		int mid = (lt+rt)/2;
		if(p <= mid){
			update(p, v, tp*2, lt, mid);
		}else{
			update(p, v, tp*2+1, mid+1, rt);
		}
		tre[tp] = max(tre[tp*2], tre[tp*2+1]);
	}
}

int query(int qlt, int qrt, int tp=1, int lt=1, int rt=n){
	if(qlt <= lt && rt <= qrt){
		return tre[tp];
	}else{
		int mid = (lt+rt)/2;
		int r = -1;
		if(qlt <= mid){
			r = max(r, query(qlt, qrt, tp*2, lt, mid));
		}
		if(qrt > mid){
			r = max(r, query(qlt, qrt, tp*2+1, mid+1, rt));
		}
		return r;
	}
}

void buildit(int tp=1, int lt=1, int rt=n){
	static int count = 0;
	if(lt == rt){
		tre[tp] = val[ido[count++]];
	}else{
		int mid = (lt+rt)/2;
		buildit(tp*2, lt, mid);
		buildit(tp*2+1, mid+1, rt);
		tre[tp] = max(tre[tp*2], tre[tp*2+1]);
		// cout << tre[tp] << " ";
	}
}

int solve(int a, int b){
	if(bs[a] == bs[b]){
		if(id[a] > id[b]){
			swap(a, b);
		}
		return query(id[a], id[b]);
	}else{
		if(bs[a] < bs[b]){
			swap(a, b);
		}
		return max(query(id[bs[a]], id[a]), solve(dad[bs[a]], b));
	}
}

int main(){
	// ios_base::sync_with_stdio(false);
	readtree();
	defeseu();
	decompose();
	buildit();
	for(int i = 0; i < m; ++i){
		int op, a, b;
		fin >> op >> a >> b;
		if(op == 0){
			update(id[a], b);
		}else if(op == 1){
			fout << solve(a, b) << "\n";
		}
	}
	return 0;
}