Cod sursa(job #2670090)

Utilizator akumariaPatrascanu Andra-Maria akumaria Data 8 noiembrie 2020 22:51:42
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.31 kb
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

#define MAXN 100003

int n, nLevel;
int nodeValues[MAXN], used[MAXN], weight[MAXN], level[MAXN];
int pathF[MAXN], pathLevel[MAXN], pathPos[MAXN], pathDim[MAXN], l[MAXN];
vector<int> arcs[MAXN], path[MAXN];
int aint[4*MAXN];



void dfs(int current_node) {
	used[current_node] = true;
	weight[current_node] = 1;

	bool is_leaf = true;
	int next_node, hn = -1;

	for(int i=0; i<arcs[current_node].size(); ++i)
		if(! used[arcs[current_node][i]]) {
			is_leaf = false;

			next_node = arcs[current_node][i];
			level[next_node] = level[current_node] + 1;
			dfs(next_node);

			weight[current_node] += weight[next_node];
			if (hn == -1 || weight[hn] < weight[next_node])
				hn = next_node;
		}

	if (is_leaf) {
		++nLevel;
		l[current_node] = nLevel;
		pathDim[nLevel] = 1;
		path[nLevel].push_back(current_node);
		return;
	}

	l[current_node] = l[hn];
	pathDim[l[current_node]] ++;
	path[l[current_node]].push_back(current_node);

	for(int i=0; i<arcs[current_node].size(); ++i) {
            next_node = arcs[current_node][i];
            if (next_node != hn && level[current_node] <= level[next_node]) {
                pathF[l[next_node]] = current_node;
                pathLevel[l[next_node]] = level[current_node];
        }
	}
}


void build_aint(int current_node, int left, int right, int start, int current_path) {
	if (left == right) {
		aint[current_node + start] = nodeValues[path[current_path][left - 1]];
		return;
	}

	int med = (left + right) / 2;

	build_aint(current_node * 2, left, med, start, current_path);
	build_aint(current_node * 2 + 1, med+1, right, start, current_path);

	if (aint[current_node * 2 + start] > aint[current_node * 2 + 1 + start])
		aint[current_node + start] = aint[current_node * 2 + start];
	else
		aint[current_node + start] = aint[current_node * 2 + start + 1];
}


void updateValue(int current_node, int left, int right, int poz, int val, int start) {
	if(left == right) {
		aint[current_node + start] = val;
		return;
	}

	int med = (left + right) / 2;
	if (poz <= med)
		updateValue(current_node * 2, left, med, poz, val, start);
	else
		updateValue(current_node * 2 + 1, med + 1, right, poz, val, start);

	if (aint[current_node * 2 + start] > aint[current_node * 2 + 1 + start])
		aint[current_node + start] = aint[current_node * 2 + start];
	else
		aint[current_node + start] = aint[current_node * 2 + start + 1];
}


int query(int current_node, int left, int right, int qLeft, int qRight, int start) {
	if (qLeft <= left && right <= qRight)
		return aint[current_node + start];

	int med = (left + right) / 2, rez1 = -1, rez2 = -1;

	if(qLeft <= med)
		rez1 = query(current_node * 2, left, med, qLeft, qRight, start);
	if(med < qRight)
		rez2 = query(current_node * 2 + 1, med+1, right, qLeft, qRight, start);

	if (rez1 > rez2)
		return rez1;
	return rez2;
}


int getMax(int x, int y) {
	int sol = 0, newSol, aux;

	while (1) {
		if (l[x] == l[y]) {
			if(level[x] > level[y]) {
				aux = y;
				y = x;
				x = aux;
			}

			newSol = query(1, 1, pathDim[l[x]], level[x] - pathLevel[l[x]], level[y] - pathLevel[l[x]], pathPos[l[x]]);

			if (newSol > sol)
				sol = newSol;
            break;
		} else {
			if (pathLevel[l[x]] < pathLevel[l[y]]) {
				aux = x;
				x = y;
				y = aux;
			}

			newSol = query(1, 1, pathDim[l[x]], 1, level[x] - pathLevel[l[x]], pathPos[l[x]]);
			if (newSol > sol)
                sol = newSol;
			x = pathF[l[x]];
		}
	}

	return sol;
}


int main() {
	freopen("heavypath.in", "r", stdin);
	freopen("heavypath.out", "w", stdout);

	int m, x, y, t;

	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; ++i)
		scanf("%d", &nodeValues[i]);
	for(int i=1; i<n; ++i) {
		scanf("%d%d", &x, &y);
		arcs[x].push_back(y);
		arcs[y].push_back(x);
	}

	level[1] = 1;
	dfs(1);

	for(int i=1; i<= nLevel; ++i) {
		reverse(path[i].begin(), path[i].end());
		if(i > 1)
			pathPos[i] = pathPos[i-1] + pathDim[i-1] * 4;
		build_aint(1, 1, pathDim[i], pathPos[i], i);
	}

	for(int i=1; i<=m; ++i) {
		scanf("%d%d%d", &t, &x, &y);

		if (t == 0)
			updateValue(1, 1, pathDim[l[x]], level[x] - pathLevel[l[x]], y, pathPos[l[x]]);
		else
			printf("%d\n", getMax(x, y));
	}

	return 0;
}