Cod sursa(job #1494650)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 1 octombrie 2015 18:17:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.16 kb
#include <vector>
#include <functional>
#include <fstream>
#include <iostream>
#include <utility>
using namespace std;

template <typename Cmp>
class max_aint{
	int n, minus_inf;
	vector<int> buf;
	Cmp c;
public:
	template <typename F>
	max_aint(const int sz, F f, Cmp cc, int min_inf): n(sz), buf(2*sz), c(cc), minus_inf(min_inf){
		for(int i = 0; i < n; ++i){
			buf[i+n] = f(i); }
		for(int i = n-1; i > 0; --i){
			buf[i] = max(buf[2*i], buf[2*i+1], c); } }
	int query(int st, int dr)const{
		int rez = minus_inf;
		for(st += n, dr += n+1; st < dr; st /= 2, dr /= 2){
			if(st%2){
				rez = max(rez, buf[st++], c); }
			if(dr%2){
				rez = max(buf[--dr], rez, c); } }
		return rez; }
	int update(int p, const int v){
		for(p += n, buf[p] = v; p > 1; p /= 2){
			buf[p/2] = max(buf[p], buf[p^1], c); } } };

struct nod_info{
	vector<int> adiac;
	int adanc = 0, size = 1, heavy_child = -1, ind_lant = -1, val_init = 0,
		father = 0, st = 0, dr = 0; };


void recon_dfs(vector<nod_info>& arb, const int cur, const int prev, vector<int>& euler){
	euler.push_back(cur);
	arb[cur].st = euler.size()-1;
	bool are_un_copil = false;
	for(const auto next : arb[cur].adiac){
		if(next != prev){
			are_un_copil = true;
			arb[next].adanc = arb[cur].adanc+1;
			arb[next].father = cur;
			recon_dfs(arb, next, cur, euler);
			arb[cur].size += arb[next].size;
			euler.push_back(cur); } }
	if(!are_un_copil){
		euler.push_back(cur); }
	arb[cur].dr = euler.size()-1;

	if(prev != -1 && (arb[prev].heavy_child == -1 ||
		arb[arb[prev].heavy_child].size < arb[cur].size)){
		arb[prev].heavy_child = cur; } }

void decide_lant_dfs(vector<nod_info>& arb, const int cur, const int prev, int& care_lant,
	vector<vector<int> >& paths){
	if(arb[cur].ind_lant == -1){
		arb[cur].ind_lant = care_lant++;
		paths.push_back({}); }
	if(arb[cur].heavy_child != -1){
		arb[arb[cur].heavy_child].ind_lant = arb[cur].ind_lant; }
	paths[arb[cur].ind_lant].push_back(cur);
	for(const auto next : arb[cur].adiac){
		if(next != prev){
			decide_lant_dfs(arb, next, cur, care_lant, paths); } } }

class heavy_path{
	vector<int> path_adanc, path_radacina;
	vector<max_aint<less<int> > > paths_aint;
	const vector<nod_info>& arb_ref;
public:
	heavy_path(vector<nod_info>& arb):
		arb_ref(arb){
		vector<vector<int> > paths;
		int nr_lanturi = 0;
		decide_lant_dfs(arb, 0, -1, nr_lanturi, paths);
		path_adanc.resize(nr_lanturi), path_radacina.resize(nr_lanturi);
		for(int i = 0; i < nr_lanturi; ++i){
			path_adanc[i] = arb[paths[i].front()].adanc;
			path_radacina[i] = paths[i].front();
			paths_aint.emplace_back(paths[i].size(),
				[&paths, &arb, i](const int x){
					return arb[paths[i][x]].val_init; },
				less<int>(), -1); } }

	void update(const int nod, const int val){
		const int wh = arb_ref[nod].ind_lant;
		paths_aint[wh].update(arb_ref[nod].adanc - path_adanc[wh], val); }
	int query(const int sus, int jos){
		int rez = 0;
		while(arb_ref[sus].ind_lant != arb_ref[jos].ind_lant){
			rez = max(rez,
				paths_aint[arb_ref[jos].ind_lant].query(0, arb_ref[jos].adanc - path_adanc[arb_ref[jos].ind_lant]));
			jos = arb_ref[path_radacina[arb_ref[jos].ind_lant]].father; }

		return max(rez,
			paths_aint[arb_ref[sus].ind_lant].query(
				arb_ref[sus].adanc - path_adanc[arb_ref[sus].ind_lant],
				arb_ref[jos].adanc - path_adanc[arb_ref[jos].ind_lant])); } };


	
int main(){
	ifstream f("heavypath.in");
	ofstream g("heavypath.out");
	int n, m;
	f >> n >> m;
	vector<nod_info> arb(n);
	for(int i = 0; i < n; ++i){
		f >> arb[i].val_init; }
	for(int i = 0, a, b; i < n-1; ++i){
		f >> a >> b;
		--a, --b;
		arb[a].adiac.push_back(b);
		arb[b].adiac.push_back(a); }
	vector<int> euler;
	recon_dfs(arb, 0, -1, euler);

	auto cmp = [&arb](const int x, const int y){
			return (x==-1) || ((y!=-1) && arb[x].adanc > arb[y].adanc); };

	max_aint<decltype(cmp)> for_lca(euler.size(), [&euler](const int x){
			return euler[x]; },
			cmp, -1);

	heavy_path hp(arb);
	for(int i = 0, t, a, b; i < m; ++i){
		f >> t >> a >> b;
		if(t == 0){
			hp.update(a-1, b); }
		else{
			--a, --b;
			int x = arb[a].st, y = arb[b].st;
			if(x > y){
				swap(x, y); }
			const int lca = for_lca.query(x, y);
			int p, q;
			g << max(p=hp.query(lca, a), q=hp.query(lca, b)) << '\n'; } }
	return 0; }