Cod sursa(job #1758372)

Utilizator TeodorCotetCotet Teodor TeodorCotet Data 17 septembrie 2016 04:34:06
Problema Heavy Path Decomposition Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.6 kb
#include <bits/stdc++.h>

using namespace std;

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

const int NMAX = 1e5 + 5;
const int MMAX = 1e5 + 5;

int n, m;

int v[NMAX];
vector<int> g[NMAX];
int lant[NMAX], posl[NMAX];
vector<int> a[NMAX];
vector<int> arb[NMAX];
int h[NMAX], sons[NMAX], father[NMAX];

void read() {

	fin >> n >> m;

	for(int i = 1; i <= n ; ++i)
		fin >> v[i];

	for(int i = 1 ; i < n ; ++i) {
		int x, y; fin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
}

void dfs(int node, int fath) {

	h[node] = h[fath] + 1;

	int heaviestChildren = -1;

	for(int x : g[node])
		if(x != fath) {
			dfs(x, node);
			sons[node] += sons[x];
			
			if(heaviestChildren == -1)
				heaviestChildren = x;

			if(sons[x] > sons[heaviestChildren])
				heaviestChildren = x;
		}

	sons[node]++;

	if(g[node].size() == 1 && node != 1) { //frunza
		heaviestChildren = node;
		lant[node] = node;
	}

	lant[node] = lant[heaviestChildren];
	a[lant[node]].push_back(node);
	posl[node] = a[lant[node]].size() - 1;
}

void dfs2(int node, int fath) {

	if(lant[node] != lant[fath])
		father[lant[node]] = fath;

	for(int x : g[node])
		if(x != fath)
			dfs2(x, node);

}

void construct(int l, int node, int st, int dr) {

	if(st == dr) {

		arb[l][node] = a[l][st];
		return ;
	}

	int mid = (st + dr) / 2;

	construct(l, node * 2, st, mid);
	construct(l, node * 2 + 1, mid + 1, dr);

	arb[l][node] = arb[l][node * 2];

	if(v[ arb[l][node] ] < v[ arb[l][node * 2 + 1] ])
		arb[l][node] = arb[l][node * 2 + 1];
}

int query(int l, int node, int st, int dr, int left, int right) {
	//caut in intervalul [left, rright]

	if(left <= st && dr <= right) 
		return arb[l][node];
	
	int mid = (st + dr) / 2;
	int indmin1 = -1, indmin2 = -1;
	//st mid dr
	if(left <= mid)
		indmin1 = query(l, node * 2, st, mid, left, right);
	if(mid + 1 <= right)
		indmin2 = query(l, node * 2 + 1, mid + 1, dr, left, right);

	if(indmin1 != -1 && indmin2 != -1) {

		if(v[indmin1] < v[indmin2])
			return indmin2;
		else 
			return indmin1;
	} else  return max(indmin1, indmin2);//unul este diferit -1
}

void constructDecompos() {

	dfs(1, 0);
	dfs2(1, 0);
/*
	for(int i = 2 ; i <= n ; ++i) 
		if(g[i].size() == 1) {
			for(int x : a[i])
				cout << x << ' ' << lant[x] <<  "  ";
			cout << "  " << father[lant[i]] << '\n';
 		}
 */

 	for(int i = 2; i <= n ; ++i)
 		if(a[i].size() > 0) {
 			arb[i].reserve(a[i].size() * 4 + 5);
 			construct(i, 1, 0, a[i].size() - 1);
 		}

}

void update(int l, int node, int st, int dr, int pos, int value) {

	if(st == dr) 
		return ;

	int mid = (st + dr) / 2;

	if(pos <= mid)
		update(l, node * 2 , st, mid, pos, value);
	else 
		update(l, node * 2 + 1, mid + 1, dr, pos, value);

	arb[l][node] = arb[l][node * 2];

	if(v[ arb[l][node] ] < v[ arb[l][node * 2 + 1] ])
		arb[l][node] = arb[l][node * 2 + 1];
}

void solve() {

	constructDecompos();

	while(m--) {

		int x, y, t;
		fin >> t >> x >> y;

		if(t == 0) {
			v[x] = y;
			update(lant[x], 1, 0, a[lant[x]].size() - 1, posl[x], y);
		}
		else {
			int ans = v[y];//cand se ajunge in radacina ambele sun egale
						//dar nu se in considerare nodul curent

			while(x != y) {

				if(lant[x] == lant[y])  {

					if(posl[x] > posl[y])
						swap(x, y);

					int q = query(lant[x], 1, 0, a[lant[x]].size() - 1, posl[x], posl[y]);
					ans = max(ans, v[q]);
					x = y;

				} else {

					if(h[father[lant[x]]] < h[father[lant[y]]])
						swap(x, y);
					int q = query(lant[x], 1, 0, a[lant[x]].size() - 1, posl[x], a[lant[x]].size() - 1);
					ans = max(ans, v[q]);
					x = father[lant[x]];
				}
			}

			fout << ans << '\n';
		}
			
	}
	
}

int main() {

	read(); solve();
	return 0;
}