Cod sursa(job #1414440)

Utilizator darrenRares Buhai darren Data 2 aprilie 2015 16:56:35
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.94 kb
#include <cstring>
#include <fstream>
#include <algorithm>

using namespace std;

int N, M;
int A[100002];
vector<int> V[100002];
bool S[100002];
int ARB[4 * 100002], Ap, A1, A2, Av;
int comp[100002], where[100002], what[100002];
int L1[100002], L2[100002], niv[100002];
int W[100002], T[100002], rT[100002];
int ST[100002];

void setall(int nod, int i1, int i2)
{
	if (i1 == i2)
	{
		ARB[nod] = A[what[i1]];
		return;
	}
	
	int mid = (i1 + i2) / 2;
	setall(nod * 2, i1, mid);
	setall(nod * 2 + 1, mid + 1, i2);
	
	ARB[nod] = max(ARB[nod * 2], ARB[nod * 2 + 1]);
}
void update(int nod, int i1, int i2)
{
	if (i1 == i2)
	{
		ARB[nod] = A[what[i1]];
		return;
	}
	
	int mid = (i1 + i2) / 2;
	if (Ap <= mid) update(nod * 2, i1, mid);
	else           update(nod * 2 + 1, mid + 1, i2);
	
	ARB[nod] = max(ARB[nod * 2], ARB[nod * 2 + 1]);
}
void query(int nod, int i1, int i2)
{
	if (A1 <= i1 && i2 <= A2)
	{
		Av = max(Av, ARB[nod]);
		return;
	}
	
	int mid = (i1 + i2) / 2;
	if (A1 <= mid) query(nod * 2, i1, mid);
	if (A2 > mid)  query(nod * 2 + 1, mid + 1, i2);
}

void preDfs(int x)
{
	S[x] = true;
	W[x] = 1;
	T[x] = x;
	
	for (auto nod : V[x])
		if (!S[nod])
		{
			rT[nod] = x;
			niv[nod] = niv[x] + 1;
			preDfs(nod);
			W[x] += W[nod];
		}
}
void Dfs(int x)
{
	S[x] = true;
	ST[++ST[0]] = x;
	
	for (auto nod : V[x])
		if (!S[nod] && 2 * W[nod] > W[x] - 1)
			T[nod] = x;
	
	for (auto nod : V[x])
		if (!S[nod])
			Dfs(nod);
	
	if (T[x] == x)
	{
		++comp[0];
		L1[comp[0]] = where[0] + 1;
		L2[comp[0]] = where[0];
		
		while (true)
		{
			comp[ST[ST[0]]] = comp[0];
			where[ST[ST[0]]] = ++where[0];
			what[where[0]] = ST[ST[0]];
			++L2[comp[0]];
			
			--ST[0];
			if (ST[ST[0] + 1] == x) break;
		}
	}
}

int queryARB(int nod1, int nod2)
{
	if (comp[nod1] == comp[nod2])
	{
		A1 = where[nod1], A2 = where[nod2], Av = 0;
		if (A1 > A2) swap(A1, A2);
		
		query(1, 1, N);
		return Av;
	}
	
	if (niv[rT[what[L2[comp[nod1]]]]] > niv[rT[what[L2[comp[nod2]]]]])
	{
		A1 = where[nod1], A2 = L2[comp[nod1]], Av = 0;
		if (A2 > A2) swap(A1, A2);
		query(1, 1, N);
		
		int val = Av;
		
		return max(val, queryARB(rT[what[L2[comp[nod1]]]], nod2));
	}
	else
	{
		A1 = where[nod2], A2 = L2[comp[nod2]], Av = 0;
		if (A2 > A2) swap(A1, A2);
		query(1, 1, N);
		
		int val = Av;
		
		return max(val, queryARB(nod1, rT[what[L2[comp[nod2]]]]));
	}
}

int main()
{
	ifstream fin("heavypath.in");
	ofstream fout("heavypath.out");
	
	fin >> N >> M;
	for (int i = 1; i <= N; ++i)
		fin >> A[i];
	for (int i = 1, nod1, nod2; i <= N - 1; ++i)
	{
		fin >> nod1 >> nod2;
		V[nod1].push_back(nod2);
		V[nod2].push_back(nod1);
	}
	
	niv[1] = 1;
	preDfs(1);
	memset(S, 0, sizeof(S));
	Dfs(1);
	
	setall(1, 1, N);
	
	for (int i = 1, type; i <= M; ++i)
	{
		fin >> type;
		if (type == 0)
		{
			int nod, val;
			fin >> nod >> val;
			
			A[nod] = val;
			Ap = where[nod];
			
			update(1, 1, N);
		}
		else
		{
			int nod1, nod2;
			fin >> nod1 >> nod2;
			fout << queryARB(nod1, nod2) << '\n';
		}
	}
	
	fin.close();
	fout.close();
}