Pagini recente » Cod sursa (job #1221326) | Cod sursa (job #303331) | Cod sursa (job #637818) | cei_mai_mari_olimpicari_runda_4 | Cod sursa (job #1097964)
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>
#define pii pair<int, int>
using namespace std;
int n, val[200100], nrord, st[200100], dr[200100], best[200100], St[200100], Stbest[200100], vf;
vector <int> G[200100], G2[200100];
bool viz[200100];
set <pii> S;
inline void Citire()
{
int i, x, y;
ifstream fin("guvern.in");
fin >> n;
for(i = 1; i < n; ++i)
{
fin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
for(i = 1; i <= n; ++i)
fin >> val[i];
// pun o radacina fictiva cu valoare mare
val[0] = 2000000000;
G[0].push_back(1);
fin.close();
}
inline bool Urmas(int a, int b) // daca a este urmas al lui b
{
if(st[b] <= st[a] && dr[a] <= dr[b])
return true;
return false;
}
inline void DFS(int x)
{
vector <int>::iterator it;
S.insert(make_pair(val[x], x)); // introduc acum si nodul asta in set
viz[x] = true;
st[x] = ++nrord; // liniarizare arbore
for(it = G[x].begin(); it != G[x].end(); ++it)
if(!viz[*it])
DFS(*it);
dr[x] = ++nrord; // liniarizare arbore
S.erase(make_pair(val[x], x)); // il scot din set ca ma intorc inapoi sus
if(x != 0)
{
// caut sus pe lantul spre radacina nodul cu val minim >= val[x]
set <pii>::iterator back = S.lower_bound(make_pair(val[x], x));
G2[(*back).second].push_back(x);
}
int bestaux;
vf = 0;
for(it = G2[x].begin(); it != G2[x].end(); ++it)
{
++vf;
St[vf] = *it;
Stbest[vf] = best[*it];
bestaux = 0;
while(vf >= 2 && Urmas(St[vf - 1], St[vf]))
{
bestaux += Stbest[vf - 1];
St[vf - 1] = St[vf];
Stbest[vf - 1] = Stbest[vf];
vf--;
}
Stbest[vf] = max(Stbest[vf], bestaux);
}
best[x] = 1;
while(vf)
{
best[x] += Stbest[vf];
vf--;
}
}
inline void Afisare()
{
ofstream fout("guvern.out");
fout << (best[0] - 1) << "\n";
fout.close();
}
int main()
{
Citire();
DFS(0);
Afisare();
return 0;
}