Cod sursa(job #2279283)

Utilizator valen.valentinValentin Valeanu valen.valentin Data 9 noiembrie 2018 12:02:03
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.11 kb
#include <stdio.h>
#include <vector>
#define SZ(x) ((int)(x.size()))
#define nmax 100010

using namespace std;

int n, m, x, y;
int totalChainsNumber;
int v[nmax], sz[nmax], parent[nmax], parentChain[nmax], numberOfChain[nmax], value[nmax];

vector <int> graph[nmax];
vector <int> chainNodes[nmax];
vector <int> arb[nmax];

int my_log2(int x)
{
	int nr = 0;
	
	while (x > 0) { x /= 2; nr++; }
	
	return nr + 1;
}

void my_swap(int &a, int &b)
{
	int aux = a; a = b; b = aux;
}

void dfs(int node, int p)
{
	sz[node] = 1;
	
	for (int i = 0; i < SZ(graph[node]); i++)
		if (graph[node][i] != p) {
			
			dfs(graph[node][i], node);
		
			parent[graph[node][i]] = node;
			sz[node] += sz[graph[node][i]];
		}
}

void hld(int node, int p, int chain_number)
{
	chainNodes[chain_number].push_back(node);
	
	int mx = -1, index_max_child = -1;
	
	for (int i = 0; i < SZ(graph[node]); i++)
		if (sz[graph[node][i]] > mx && graph[node][i] != p) {
			
			mx = sz[graph[node][i]];
			index_max_child = graph[node][i];
		}
		
	// not leaf
	if (mx != -1) { 
		
		parentChain[index_max_child] = parentChain[node]; 
		numberOfChain[index_max_child] = chain_number; 
		
		hld(index_max_child, node, chain_number); 
	}
	
	// for other nodes than max start a new chain
	for (int i = 0; i < SZ(graph[node]); i++)
		if (graph[node][i] != index_max_child && graph[node][i] != p) {
			
			totalChainsNumber++;
			
			parentChain[graph[node][i]] = node;
			numberOfChain[graph[node][i]] = totalChainsNumber;
			hld(graph[node][i], node, totalChainsNumber);
		}
}

void build(int idx, int node, int l, int r)
{
	if (l == r) {
		
		arb[idx][node] = v[chainNodes[idx][l - 1]]; 
		
		return;
	}
	
	int m = (l + r) / 2;
	
	build(idx, node * 2, l, m);
	build(idx, node * 2 + 1, m + 1, r);
	
	arb[idx][node] = max(arb[idx][node * 2], arb[idx][node * 2 + 1]);
}

void update(int idx, int node, int l, int r, int pos, int val)
{
	if (l == r) {
		
		arb[idx][node] = val;
		
		return;
	}
	
	int m = (l + r) / 2;
	
	if (pos <= m) update(idx, node * 2, l, m, pos, val); else
		update(idx, node * 2 + 1, m + 1, r, pos, val);
		
	arb[idx][node] = max(arb[idx][node * 2], arb[idx][node * 2 + 1]);
}

int query(int idx, int node, int l, int r, int pl, int pr)
{
	if (l >= pl && r <= pr) return arb[idx][node];
	
	int answer = -1;
	int m = (l + r) / 2;
	
	if (pl <= m) answer = max(answer, query(idx, node * 2, l, m, pl, pr));
	if (pr > m) answer = max(answer, query(idx, node * 2 + 1, m + 1, r, pl, pr));
	
	return answer;
}

void build_arb(int idx)
{
	int size = SZ(chainNodes[idx]);
	
	arb[idx].reserve(size * my_log2(size));
	
	build(idx, 1, 1, size);
	
	for (int i = 0; i < SZ(chainNodes[idx]); i++) value[chainNodes[idx][i]] = i + 1;
}

int _query(int l, int r)
{
	int answer = -1;
	
	while (numberOfChain[l] != numberOfChain[r]) {
		
		if (numberOfChain[l] > numberOfChain[r]) { 
		
			int x = numberOfChain[l];
		
			answer = max(answer, query(x, 1, 1, SZ(chainNodes[x]), 1, value[l]));
			
			l = parentChain[l];
		} else {
			
			int x = numberOfChain[r];
			
			answer = max(answer, query(x, 1, 1, SZ(chainNodes[x]), 1, value[r]));
			
			r = parentChain[r];
		}
		
	}
	
	int x = numberOfChain[l];
	
	if (value[l] > value[r]) my_swap(l, r);
	
	answer = max(answer, query(x, 1, 1, SZ(chainNodes[x]), value[l], value[r]));
	
	return answer;
}

int main()
{
	freopen("heavypath.in", "r", stdin);
	freopen("heavypath.out", "w", stdout);
	
	scanf("%d %d", &n, &m);
	
	for (int i = 1; i <= n; i++) scanf("%d", &v[i]);
	
	for (int i = 1; i < n; i++) {
		
		scanf("%d %d", &x, &y);
		
		graph[x].push_back(y);
		graph[y].push_back(x);
	}
	
	parentChain[1] = 0;
	numberOfChain[1] = 1;
	totalChainsNumber = 1;
	
	dfs(1, 0);
	hld(1, 0, 1);
	
	for (int i = 1; i <= totalChainsNumber; i++) build_arb(i);
	
	for (int i = 1; i <= m; i++) {
		
		int t, x, y;
		
		scanf("%d %d %d", &t, &x, &y);
		
		if (t == 0) update(numberOfChain[x], 1, 1, SZ(chainNodes[numberOfChain[x]]), value[x], y); else
			printf("%d\n", _query(x, y));
		
	}
	
	return 0;
}