Cod sursa(job #2274791)

Utilizator TincaMateiTinca Matei TincaMatei Data 2 noiembrie 2018 15:03:30
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.03 kb
#include <bits/stdc++.h>

using namespace std;

template<int n, typename T, typename Updater>
class Aint {
private:
	T neutralQry, initval;
	T *aint;
	Updater upd;
public:
	Aint(T _neutralQry, T _initval) {
		initval = _initval;
		neutralQry = _neutralQry;

		aint = new T[1 + 4 * n];
		
		for(int i = 0; i <= 4 * n; ++i)
			aint[i] = initval;
	}
	void update(int poz, T val, int l = 1, int r = n, int nod = 1) {
		if(poz < l || r < poz)
			return ;
		if(l == r && l == poz)
			aint[nod] = upd.update(aint[nod], val);

		int mid = (l + r) / 2;
		if(l < r) {
			update(poz, val, l, mid, 2 * nod);
			update(poz, val, mid + 1, r, 2 * nod + 1);
			aint[nod] = upd.query(aint[2 * nod], aint[2 * nod + 1]);
		}
	}
	T query(int i, int j, int l = 1, int r = n, int nod = 1) {
		if(r < i || j < l || r < l)
			return neutralQry;
		if(i <= l && r <= j)
			return aint[nod];
		int mid = (l + r) / 2;
		return upd.query(query(i, j, l, mid, 2 * nod),
		                 query(i, j, mid + 1, r, 2 * nod + 1));
	}
};

const int MAX_N = 100000;

vector<int> graph[MAX_N];

struct Upd {
	static inline int update(int a, int b) {
		return b;
	}
	static inline int query(int a, int b) {
		return std::max(a, b);
	}
};

Aint<MAX_N, int, Upd> aint(-1, -1);

int v[1+MAX_N];
int heavyId[1+MAX_N], head[1+MAX_N], depth[1+MAX_N], parent[1+MAX_N], lastid;
int subarb[1+MAX_N];

void dfs(int nod, int papa = 0) {
	subarb[nod] = 1;
	parent[nod] = papa;
	for(auto it: graph[nod])
		if(it != papa) {
			depth[it] = depth[nod] + 1;
			dfs(it, nod);
			subarb[nod] += subarb[it];
		}
}

void heavyTraversal(int nod, int headCh, int papa = 0) {
	int heavySon = -1;
	head[nod] = headCh;
	heavyId[nod] = ++lastid;
	for(auto it: graph[nod])
		if(it != papa) {
			if(heavySon == -1)
				heavySon = it;
			else if(subarb[it] > subarb[heavySon])
				heavySon = it;
		}
	
	if(heavySon != -1)
		heavyTraversal(heavySon, headCh, nod);
	
	for(auto it: graph[nod])
		if(it != heavySon && it != papa)
			heavyTraversal(it, it, nod);
}

int heavyQuery(int u, int v) {
	if(head[u] == head[v]) {
		if(depth[u] > depth[v])
			std::swap(u, v);
		return aint.query(heavyId[u], heavyId[v]);
	} else {
		if(depth[head[u]] < depth[head[v]])
			std::swap(u, v);
		return std::max(aint.query(heavyId[head[u]], heavyId[u]), 
		                heavyQuery(parent[head[u]], v));
	}
}

int main() {
#ifdef HOME
	FILE *fin = fopen("input.in", "r");
	FILE *fout = fopen("output.out", "w");
#else
	FILE *fin = fopen("heavypath.in", "r");
	FILE *fout = fopen("heavypath.out", "w");
#endif
	
	int n, m, a, b;
	
	fscanf(fin, "%d%d", &n, &m);
	
	for(int i = 1; i <= n; ++i)
		fscanf(fin, "%d", &v[i]);
	
	for(int i = 0; i < n - 1; ++i) {
		fscanf(fin, "%d%d", &a, &b);
		graph[a].push_back(b);
		graph[b].push_back(a);
	}

	dfs(1);
	heavyTraversal(1, 1);

	for(int i = 1; i <= n; ++i)
		aint.update(heavyId[i], v[i]);
	
	for(int i = 0; i < m; ++i) {
		int t, x, y;
		fscanf(fin, "%d%d%d", &t, &x, &y);
		if(t == 0)
			aint.update(heavyId[x], y);
		else
			fprintf(fout, "%d\n", heavyQuery(x, y));
	}


#ifdef HOME
	fclose(fin);
	fclose(fout);
#endif
	return 0;
}