Cod sursa(job #634000)

Utilizator darrenRares Buhai darren Data 15 noiembrie 2011 13:00:33
Problema Guvern Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.22 kb
#include <cstring>
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

const int INF = 0x3f3f3f3f;
const int SIZE = 200002;

typedef vector<int> VI;

int N, result;
VI V[SIZE], Term[SIZE], aux;
int val[SIZE], pos[SIZE], pose[SIZE], where[SIZE], pnow;
int up[SIZE], down[SIZE];
bool S[SIZE];

int ARB[4 * SIZE], EL[4 * SIZE];
int Apos, Aval, Aplus;
void update(int nod, int i1, int i2)
{
	if (i1 == i2)
	{
		ARB[nod] = Aval;
		EL[nod] = Aplus;
		return;
	}
	
	int mid = (i1 + i2) >> 1;
	if (Apos <= mid) update(nod * 2, i1, mid);
	else             update(nod * 2 + 1, mid + 1, i2);
	
	EL[nod] = EL[nod * 2] + EL[nod * 2 + 1];
}
void query(int nod, int i1, int i2)
{
	if (EL[nod] == 0) return;
	if (i1 == i2)
	{
		Aval = ARB[nod];
		return;
	}
	
	int mid = (i1 + i2) >> 1;
	if (Apos > mid) query(nod * 2 + 1, mid + 1, i2);
	else
	{
		query(nod * 2, i1, mid);
		if (Aval == 0 && EL[nod * 2 + 1] != 0)
			query(nod * 2 + 1, mid + 1, i2);
	}
}

inline bool compare(const int& i1, const int& i2)
{
	return val[i1] < val[i2];
}
inline bool compare_euler(const int& i1, const int& i2)
{
	return pos[i1] < pos[i2];
}

void compM(int x)
{
	S[x] = true;
	pos[x] = ++pnow;
	
	Apos = val[x] + 1, Aval = 0;
	query(1, 1, N);
	where[x] = Aval;
	
	if (Aval != 0) Term[Aval].push_back(x);
	
	Apos = val[x], Aval = x, Aplus = 1;
	update(1, 1, N);
	
	for (VI::iterator it = V[x].begin(); it != V[x].end(); ++it)
		if (!S[*it])
			compM(*it);
	
	Apos = val[x], Aval = x, Aplus = 0;
	update(1, 1, N);
	
	pose[x] = ++pnow;
}
void dfsUp(int x)
{
	S[x] = true;
	if (where[x] != 0)
		up[x] = up[where[x]] + 1;
	for (VI::iterator it = V[x].begin(); it != V[x].end(); ++it)
		if (!S[*it])
			dfsUp(*it);
}
void dfsDown(int x)
{
	S[x] = true;
	for (VI::iterator it = V[x].begin(); it != V[x].end(); ++it)
		if (!S[*it])
			dfsDown(*it);
	
	sort(Term[x].begin(), Term[x].end(), compare_euler);
	sort(V[x].begin(), V[x].end(), compare_euler);
	
	down[x] = 1;
	
	VI::iterator aux = Term[x].begin();
	for (VI::iterator it = V[x].begin(); it != V[x].end(); ++it)
	{
		int maxnow = 0;
		while (aux != Term[x].end() && pos[*aux] >= pos[*it] && pose[*aux] <= pose[*it])
		{
			maxnow = max(maxnow, down[*aux]);
			++aux;
		}
		down[x] += maxnow;
	}
}

int main()
{
	ifstream fin("guvern.in");
	ofstream fout("guvern.out");
	
	fin >> N;
	for (int i = 1, nod1, nod2; i < N; ++i)
	{
		fin >> nod1 >> nod2;
		V[nod1].push_back(nod2);
		V[nod2].push_back(nod1);
	}
	for (int i = 1; i <= N; ++i)
	{
		fin >> val[i];
		pos[i] = i;
	}
	
	// I. Normalizare + realizarea muchiilor obligatorii + euler
	sort(pos + 1, pos + N + 1, compare);
	for (int i = 1; i <= N; ++i)
		val[pos[i]] = i;
	compM(1);
	
	/* verificare
	for (int i = 1; i <= N; ++i) fout << where[i] << '\n';
	*/
	
	// II. Dfs - construirea up[x]
	memset(S, 0, sizeof(S));
	dfsUp(1);
	
	/* verificare 
	for (int i = 1; i <= N; ++i) fout << up[i] << ' ';
	*/
	
	// III. Dfs - construirea down[x]
	memset(S, 0, sizeof(S));
	dfsDown(1);
	
	// IV. Result
	for (int i = 1; i <= N; ++i)
		result = max(result, down[i] + up[i]);
	fout << result << '\n';
	
	fin.close();
	fout.close();
}