Cod sursa(job #614870)

Utilizator darrenRares Buhai darren Data 7 octombrie 2011 20:14:13
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.46 kb
#include <cstring>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int SIZE = 100002;

int N, M;
int A[SIZE], Son[SIZE], T[SIZE];
vector<int> V[SIZE], Lant[SIZE];
int where[SIZE], whpos[SIZE], sL;
int in[SIZE], out[SIZE], sE;
bool heavy[SIZE], isheavy[SIZE];

bool is_str(int nod1, int nod2)
{
	return in[nod1] <= in[nod2] && out[nod1] >= out[nod2];
}
int LCA(int nod1, int nod2) // TO DO
{
	if (is_str(nod1, nod2))
		return nod1;
	if (is_str(nod2, nod1))
		return nod2;

	while (!is_str(Lant[where[nod1]].back(), nod2))
		nod1 = T[Lant[where[nod1]].back()];
	if (is_str(nod1, nod2))
		return nod1;

	int step, nowLCA;
	for (step = 1; (step << 1) < Lant[where[nod1]].size(); step <<= 1);
	for (nowLCA = -1; step; step >>= 1)
		if (nowLCA + step < Lant[where[nod1]].size() && !is_str(Lant[where[nod1]][nowLCA + step], nod2))
			nowLCA += step;
	++nowLCA;

	return Lant[where[nod1]][nowLCA];
}

int qPos, Val, result, I1, I2;
int AINT[SIZE * 4];
void update(int nod, int s1, int s2)
{
	if (s1 == s2)
	{
		AINT[nod] = Val;
		return;
	}

	int mid = (s1 + s2) >> 1;
	if (qPos <= mid) update(nod * 2, s1, mid);
	else             update(nod * 2 + 1, mid + 1, s2);

	AINT[nod] = max(AINT[nod * 2], AINT[nod * 2 + 1]);
}
void query(int nod, int s1, int s2)
{
	if (I1 <= s1 && s2 <= I2)
	{
		result = max(result, AINT[nod]);
		return;
	}

	int mid = (s1 + s2) >> 1;
	if (I1 <= mid) query(nod * 2, s1, mid);
	if (I2 > mid)  query(nod * 2 + 1, mid + 1, s2);
}

void preDfs(int x)
{
	Son[x] = 1;
	for (vector<int>::iterator it = V[x].begin(); it != V[x].end(); ++it)
		if (*it != T[x])
		{
			in[*it] = ++sE;

			T[*it] = x;
			preDfs(*it);
			Son[x] += Son[*it];

			out[*it] = ++sE;
		}
}
void heavy_light(int x)
{
    for (vector<int>::iterator it = V[x].begin(); it != V[x].end(); ++it)
		if (*it != T[x] && Son[*it] >= Son[x] / 2)
		{
			heavy[*it] = true;
			isheavy[x] = true;
			break;
		}
    for (vector<int>::iterator it = V[x].begin(); it != V[x].end(); ++it)
        if (*it != T[x])
            heavy_light(*it);

	if (!isheavy[x] && where[x] == 0)
	{
		int now = x;

		++sL;
		while (true)
		{
			++qPos;
			Val = A[now];
			update(1, 1, N);

			Lant[sL].push_back(now);
			where[now] = sL;
			whpos[now] = qPos;

			if (!heavy[now]) break;
			now = T[now];
		}
	}
}

int getResult(int now, int nodLCA)
{
	int maxnow = 0;
	while (LCA(Lant[where[now]].back(), nodLCA) == nodLCA)
	{
        result = 0;
		I1 = whpos[now], I2 = whpos[Lant[where[now]].back()];
		query(1, 1, N);

		maxnow = max(maxnow, result);

		if (Lant[where[now]].back() == nodLCA)
		{
			now = nodLCA;
			break;
		}
		now = T[Lant[where[now]].back()];
	}
	if (now != nodLCA)
	{
        result = 0;
		I1 = whpos[now], I2 = whpos[nodLCA];
		query(1, 1, N);

		maxnow = max(maxnow, result);
	}
	else
		maxnow = max(maxnow, A[now]);

	return maxnow;
}

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; ++i)
	{
		fin >> nod1 >> nod2;
		V[nod1].push_back(nod2);
		V[nod2].push_back(nod1);
	}

	in[1] = ++sE;

    preDfs(1);
	heavy_light(1);

	out[1] = ++sE;

	for (int i = 1, t, x, y; i <= M; ++i)
	{
		fin >> t >> x >> y;

		if (t == 0)
		{
			qPos = whpos[x];
			Val = y;
			update(1, 1, N);

			A[x] = y;
		}
		else
		{
			int nodLCA = LCA(x, y), maxnow = 0;
			maxnow = max(getResult(x, nodLCA), getResult(y, nodLCA));

			fout << maxnow << '\n';
		}
	}


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