Cod sursa(job #2196255)

Utilizator dorin31Geman Dorin Andrei dorin31 Data 18 aprilie 2018 21:51:11
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.63 kb
#include <bits/stdc++.h>
#define maxN 100001

using namespace std;

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

int n, tests, mxx;
int value[maxN], subTreeNodes[maxN], level[maxN], dad[maxN], whereInPath[maxN], whichPath[maxN], pathsNo;
vector<int> v[maxN], segmentTree[maxN], path[maxN];
bool visited[maxN];

inline int maxim(int x, int y) {
	return x > y ? x : y;
}

void basicDFS(int x, int father = 0) {
	dad[x] = father;
	visited[x] = 1;
	level[x] = level[dad[x]] + 1;
	subTreeNodes[x] = 1;
	for (int i = 0 ; i < v[x].size() ; ++i)
		if (!visited[v[x][i]]) {
			basicDFS(v[x][i], x);
			subTreeNodes[x] += subTreeNodes[v[x][i]];
		}
}

void pathDFS(int x) {
	visited[x] = 0;
	int nodeToChoose = 0, mx = 0;
	for (int i = 0 ; i < v[x].size() ; ++i)
		if (visited[v[x][i]]) {
			pathDFS(v[x][i]);
			if (subTreeNodes[v[x][i]] > mx) {
				nodeToChoose = v[x][i];
				mx = subTreeNodes[v[x][i]];
			}
		}
	if (nodeToChoose == 0) {
		path[++pathsNo].push_back(x);
		whereInPath[x] = 0;
		whichPath[x] = pathsNo;
	}
	else {
		path[whichPath[nodeToChoose]].push_back(x);
		whereInPath[x] = path[whichPath[nodeToChoose]].size() - 1;
		whichPath[x] = whichPath[nodeToChoose]; 
	}
}

void buildSegmentTree(int node, int left, int right, int cnt) {
	if (left == right) {
		segmentTree[cnt][node] = value[path[cnt][left]];
		return;
	}
	int mid = (left+right)>>1;
	buildSegmentTree(node*2, left, mid, cnt);
	buildSegmentTree(node*2+1, mid+1, right, cnt);
	segmentTree[cnt][node] = maxim(segmentTree[cnt][node*2], segmentTree[cnt][node*2+1]);
}

void updateSegmentTree(int node, int left, int right, int val, int pos, int cnt) {
	if (left == right) {
		segmentTree[cnt][node] = val;
		return;
	}
	int mid = (left+right)>>1;
	if (pos <= mid)
		updateSegmentTree(node*2, left, mid, val, pos, cnt);
	else
		updateSegmentTree(node*2+1, mid+1, right, val, pos, cnt);
	segmentTree[cnt][node] = maxim(segmentTree[cnt][node*2], segmentTree[cnt][node*2+1]);
}

void querySegmentTree(int node, int left, int right, int a, int b, int cnt) {
	if (a <= left && right <= b) {
		if (segmentTree[cnt][node] > mxx) mxx = segmentTree[cnt][node];
		return;
	}
	int mid = (left+right)>>1;
	if (a <= mid) querySegmentTree(node*2, left, mid, a, b, cnt);
	if (mid < b) querySegmentTree(node*2+1, mid+1, right, a, b, cnt);
}

int solveHPD(int x, int y) {
	int maxNode = 0;
	while (1) {
		if (level[dad[path[whichPath[x]].back()]] < level[dad[path[whichPath[y]].back()]])
			swap(x,y);
		if (whichPath[x] == whichPath[y]) {
			int start = min(whereInPath[x], whereInPath[y]);
			int finish = maxim(whereInPath[x], whereInPath[y]);
			mxx = 0;
			querySegmentTree(1, 0, path[whichPath[x]].size()-1, start, finish, whichPath[x]);
			return max(maxNode, mxx);
		}
		mxx = 0;
		querySegmentTree(1, 0, path[whichPath[x]].size()-1, whereInPath[x], path[whichPath[x]].size()-1, whichPath[x]);
		maxNode = maxim(maxNode, mxx);
		x = dad[path[whichPath[x]].back()];
	}
}

int main() {
	fin >> n >> tests;
	for (int i = 1 ; i <= n ; ++i)
		fin >> value[i];
	for (int x, y, i = 0 ; i < n-1 ; ++i) {
		fin >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
	}

	basicDFS(1);
	pathDFS(1);

	for (int i = 1 ; i <= pathsNo ; ++i) {
		segmentTree[i].resize(4 * path[i].size());
		buildSegmentTree(1, 0, path[i].size()-1, i);
	}

	while (tests--) {
		int t, x, y;
		fin >> t >> x >> y;
		if (!t) {
			value[x] = y;
			updateSegmentTree(1, 0, path[whichPath[x]].size() - 1, y, whereInPath[x], whichPath[x]);
		}
		else
			fout << solveHPD(x,y) << '\n';
	}

	fin.close();
	fout.close();

	// for (int i = 1 ; i <= pathsNo ; ++i) {
	// 	for (int j = 0 ; j < path[i].size() ; ++j)
	// 		cout << path[i][j] << ' ';
	// 	cout << '\n';
	// }

	return 0;

}