Cod sursa(job #2206808)

Utilizator Chirita_MateiChirita Matei Chirita_Matei Data 23 mai 2018 20:47:33
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.36 kb

#include <bits/stdc++.h>

using namespace std;
ofstream fout("heavypath.out");
ifstream fin("heavypath.in");

const int NMax = 100010;
vector<int> G[NMax];

class Path {
public:
	vector<int> P;
	vector<int> T;
	int parent;

	Path() {
		P.clear();
		T.clear();
		parent = 0;
	}

	void update(int node, int st, int dr, int pos, int val) {
		if (st == dr) { T[node] = val; return; }

		int mid = (st + dr) / 2;
		if (pos <= mid) update(node * 2, st, mid, pos, val);
		else            update(node * 2 + 1, mid + 1, dr, pos, val);

		T[node] = max(T[node * 2], T[node * 2 + 1]);
	}

	int maxim(int node, int st, int dr, int ql, int qr) {
		if (st == ql && dr == qr) return T[node];

		int mid = (st + dr) / 2;
		int nr1 = 0, nr2 = 0;

		if (ql <= mid) nr1 = maxim(node * 2, st, mid, ql, min(qr, mid));
		if (qr > mid)  nr2 = maxim(node * 2 + 1, mid + 1, dr, max(ql, mid + 1), qr);

		return max(nr1, nr2);
	}

	void addToPath(int node) {
		P.push_back(node);
	}
};

class Node {
public:
	int niv;
	int sub;
	int pos;
	int val;
	int path;
};

vector<Path> paths;
vector<Node> nodes(NMax);

void makePaths(int node, int prev, int level) {
	int maxi = 0;
	int connect = 0;

	nodes[node].niv = level;

	for (int i = 0; i < G[node].size(); i++) {
		int next = G[node][i];
		if (next == prev) continue;

		makePaths(next, node, level + 1);

		if (nodes[next].sub > maxi) {
			maxi = nodes[next].sub;
			connect = next;
		}
	}

	if (!maxi) {
		Path aux;
		aux.addToPath(node);
		paths.push_back(aux);
		nodes[node].path = paths.size() - 1;
		nodes[node].sub = 1;
		return;
	}

	paths[nodes[connect].path].addToPath(node);
	nodes[node].path = nodes[connect].path;
	nodes[node].sub = nodes[connect].sub + 1;

	for (int i = 0; i < G[node].size(); i++) {
		int next = G[node][i];
		if (next == prev) continue;

		if (next != connect) {
			paths[nodes[next].path].parent = node;
		}
	}
}

void reversePathsAndMakeTrees() {
	for (int i = 0; i < paths.size(); i++) {
		reverse(paths[i].P.begin(), paths[i].P.end());

		vector<int> aux = paths[i].P;
		paths[i].T.resize(4 * aux.size() + 1);

		for (int j = 0; j < aux.size(); j++) {
			paths[i].update(1, 1, aux.size(), j + 1, nodes[aux[j]].val);
			nodes[aux[j]].pos = j + 1;
		}
	}
}

void solve1(int node, int val) {
	nodes[node].val = val;
	paths[nodes[node].path].update(1, 1, paths[nodes[node].path].P.size(), nodes[node].pos, val);
}

int solve2(int x, int y) {
	if (nodes[paths[nodes[x].path].P[0]].niv < nodes[paths[nodes[y].path].P[0]].niv) swap(x, y);

	if (nodes[x].path == nodes[y].path) return paths[nodes[x].path].maxim(1, 1, paths[nodes[x].path].P.size(), min(nodes[x].pos, nodes[y].pos), max(nodes[x].pos, nodes[y].pos));
	else return max(paths[nodes[x].path].maxim(1, 1, paths[nodes[x].path].P.size(), 1, nodes[x].pos), solve2(paths[nodes[x].path].parent, y));
}

void query(int m) {
	int x, y, o;
	for (int i = 1; i <= m; i++) {
		fin >> o >> x >> y;

		switch (o) {
		case 0: solve1(x, y); break;
		case 1: fout << solve2(x, y) << '\n'; break;
		}
	}
}

int main()
{
	int n, m, x, y;

	fin >> n >> m;

	for (int i = 1; i <= n; i++) fin >> nodes[i].val;
	for (int i = 1; i < n; i++) {
		fin >> x >> y;

		G[x].push_back(y);
		G[y].push_back(x);
	}

	makePaths(1, 0, 0);
	reversePathsAndMakeTrees();
	query(m);


	return 0;
}