Cod sursa(job #1745522)

Utilizator fanache99Constantin-Buliga Stefan fanache99 Data 22 august 2016 01:42:18
Problema Guvern Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.21 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;

ifstream cin("guvern.in");
ofstream cout("guvern.out");

const int MAXN = 200000;

vector<int> g[1 + MAXN], links[1 + MAXN];
set<pair<int, int> > grandfathers;
int value[1 + MAXN], dp[1 + MAXN], upwards[1 + MAXN];
int first[1 + MAXN], last[1 + MAXN], FuckYouSTL = 0;
int eventCount = 0;
pair<pair<int, int>, int> event[1 + MAXN];
bool seen[1 + MAXN];
int best[1 + MAXN];

void DFS(int node, int father) {
    auto it = grandfathers.lower_bound(make_pair(value[node], 0));
    if (it != grandfathers.end())
        upwards[node] = it->second;
    else
        upwards[node] = 0;
    links[upwards[node]].push_back(node);
    grandfathers.insert(make_pair(value[node], node));
    FuckYouSTL++;
    first[node] = FuckYouSTL;
    for (auto &son : g[node])
        if (son != father)
            DFS(son, node);
    grandfathers.erase(make_pair(value[node], node));
    last[node] = FuckYouSTL;
}

int BinarySearch() {
    sort(event + 1, event + eventCount + 1);
    for (int i = 1; i <= eventCount; i++) {
        int left = 1, right = i - 1, answer = 0;
        while (left <= right) {
            int middle = (left + right) / 2;
            if (event[middle].first.first < event[i].first.second) {
                answer = middle;
                left = middle + 1;
            }
            else
                right = middle - 1;
        }
        best[i] = max(best[i - 1], event[i].second + best[answer]);
    }
    return best[eventCount];
}

void Solve(int node) {
    seen[node] = true;
    for (auto &son : links[node])
        if (!seen[son])
            Solve(son);
    eventCount = 0;
    for (auto &son : links[node]) {
        eventCount++;
        event[eventCount] = make_pair(make_pair(last[son], first[son]), dp[son]);
    }
    dp[node] = 1 + BinarySearch();
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for (int i = 1; i <= n; i++)
        cin >> value[i];
    DFS(1, -1);
    Solve(0);
    cout << dp[0] - 1;
    return 0;
}