Cod sursa(job #2787588)

Utilizator cezar_titianuTitianu Cezar cezar_titianu Data 23 octombrie 2021 18:44:39
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.05 kb
#include <fstream>
#include <vector>
#include <bitset>
#include <cmath>
#include <algorithm>

struct node {
	int val, siz;
	int lvl;
	int pos, root;
	std::vector <int> par;
	std::vector <int> con;
};

int nrn;

node web[100005];

std::bitset <100005> viz;

int aint[400005];

void update(int node, int posl, int posr, int pos, int val) {
	if (posl == posr) {
		aint[node] = val;
	}
	else {
		int mid = (posl + posr) / 2;
		if (pos <= mid) {
			update((node << 1) + 1, posl, mid, pos, val);
		}
		else {
			update((node << 1) + 2, mid + 1, posr, pos, val);
		}
		aint[node] = std::max(aint[(node << 1) + 1], aint[(node << 1) + 2]);
	}
}

int query(int node, int posl, int posr, int pos1, int pos2) {
	if (posl == pos1 && posr == pos2) {
		return aint[node];
	}
	else {
		int mid = (posl + posr) / 2, ans = 0;
		if (pos1 <= mid) {
			ans = query((node << 1) + 1, posl, mid, pos1, std::min(pos2, mid));
		}
		if (mid < pos2) {
			ans = std::max(ans, query((node << 1) + 2, mid + 1, posr, std::max(pos1, mid + 1), pos2));
		}
		return ans;
	}
}

bool sizcomp(int nr1, int nr2) {
	return web[nr1].siz > web[nr2].siz;
}

void sizdfs(int pos) {
	static int lvl = 0;
	web[pos].siz = 1;
	web[pos].lvl = lvl;
	while ((1 << web[pos].par.size()) <= lvl) {
		web[pos].par.push_back(web[web[pos].par.back()].par[web[pos].par.size() - 1]);
	}
	viz[pos] = true;
	lvl++;
	for (int chd : web[pos].con) {
		if (!viz[chd]) {
			web[chd].par.push_back(pos);
			sizdfs(chd);
			web[pos].siz += web[chd].siz;
		}
	}
	lvl--;
}

void aintdfs(int pos) {
	static int aintcnt = 1, poslast = 1;
	int jump = 0;
	std::sort(web[pos].con.begin(), web[pos].con.end(), sizcomp);
	viz[pos] = true;
	web[pos].pos = aintcnt;
	web[pos].root = poslast;
	update(0, 1, nrn, aintcnt, web[pos].val);
	for (int index = 0; index < web[pos].con.size(); index++) {
		if (web[pos].con[index] == web[pos].par[0]) {
			jump++;
		}
		else {
			if (jump) {
				web[pos].con[index - jump] = web[pos].con[index];
			}
			aintcnt++;
			if (index == jump) {
				aintdfs(web[pos].con[index]);
			}
			else {
				poslast = web[pos].con[index];
				aintdfs(web[pos].con[index]);
			}
		}
	}
	while (jump--) {
		web[pos].con.pop_back();
	}
}

int lca(int pos1, int pos2) {
	for (int index = std::max(web[pos1].par.size(), web[pos2].par.size()); web[pos1].lvl !=  web[pos2].lvl && index >= 0; index--) {
		if (web[pos1].lvl - web[pos2].lvl >= (1 << index)) {
			pos1 = web[pos1].par[index];
		}
		if (web[pos2].lvl - web[pos1].lvl >= (1 << index)) {
			pos2 = web[pos2].par[index];
		}
	}
	if (pos1 == pos2) {
		return pos1;
	}
	for (int index = web[pos1].par.size() - 1; index >= 0; index--) {
		if (web[pos1].par.size() > index && web[pos1].par[index] != web[pos2].par[index]) {
			pos1 = web[pos1].par[index];
			pos2 = web[pos2].par[index];
		}
	}
	return web[pos1].par[0];
}

int main() {
	std::ifstream fin("heavypath.in");
	std::ofstream fout("heavypath.out");
	int nrm, pos1, pos2, cer, nrx, nry;
	int cpar, ans;
	fin >> nrn >> nrm;
	for (int index = 1; index <= nrn; index++) {
		fin >> web[index].val;
	}
	for (int index = 0; index < nrn - 1; index++) {
		fin >> pos1 >> pos2;
		web[pos1].con.push_back(pos2);
		web[pos2].con.push_back(pos1);
	}
	web[1].par.push_back(-1);
	viz.reset();
	sizdfs(1);
	viz.reset();
	aintdfs(1);
	for (int index = 0; index < nrm; index++) {
		fin >> cer >> nrx >> nry;
		if (cer) {
			cpar = lca(nrx, nry);
			ans = 0;
			while (web[web[nrx].root].lvl > web[cpar].lvl) {
				ans = std::max(ans, query(0, 1, nrn, web[web[nrx].root].pos, web[nrx].pos));
				nrx = web[web[nrx].root].par[0];
			}
			ans = std::max(ans, query(0, 1, nrn, web[cpar].pos, web[nrx].pos));
			while (web[web[nry].root].lvl > web[cpar].lvl) {
				ans = std::max(ans, query(0, 1, nrn, web[web[nry].root].pos, web[nry].pos));
				nry = web[web[nry].root].par[0];
			}
			ans = std::max(ans, query(0, 1, nrn, web[cpar].pos, web[nry].pos));
			fout << ans << '\n';
		}
		else {
			update(0, 1, nrn, web[nrx].pos, nry);
		}
	}
}