Cod sursa(job #1739019)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 8 august 2016 14:06:35
Problema Guvern Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <cstdio>
#include <set>
#include <vector>

using namespace std;

constexpr int maxN = 200000 + 1;

int to[maxN];
vector <int> adj[maxN];
vector <int> boundSons[maxN];
int cost[maxN];
int delta[maxN][2];

struct costCmp {
  inline bool operator () ( const int &x, const int &y ) const {
    return cost[x] < cost[y];
  }
};

set <int, costCmp> sortedStack;

void getBounds( const int node, const int parent = -1 ) {
  static int currentDelta = 0;
  delta[node][0] = currentDelta++;

  const set <int, costCmp> :: iterator iter = sortedStack.lower_bound(node);
  if (iter == sortedStack.end())
    to[node] = 0;
  else
    to[node] = *iter;
  boundSons[to[node]].emplace_back(node);
  
  sortedStack.insert(node);
  for (const auto &son : adj[node])
    if (son != parent)
      getBounds(son, node);
  
  sortedStack.erase(node);
  delta[node][1] = currentDelta;
}

struct Event {
  int b, e;
  int cost;

  inline bool operator <(const Event &other) const {
    return e < other.e;
  }
} E[maxN];

int dp[maxN];      // dp[i] = numarul maxim de noduri selectate din subarborele lui i, fara a alege noduri care obliga stramosi 
int eventDp[maxN]; // eventDp[i] = numarul maxim de evenimente pe care le putem alege fara a se intersecta din primele i

void dfs( const int node, const int parent = -1 ) {
  for (const auto &son : adj[node])
    if (son != parent)
      dfs(son, node);  

  int numEvents = 0;
  for (const auto &boundSon : boundSons[node]) {
    E[numEvents].b = delta[boundSon][0];
    E[numEvents].e = delta[boundSon][1];
    E[numEvents].cost = dp[boundSon];
    numEvents++;
  }

  // u in subarb[v] si v in subarb[node]
  // cost[u] > cost[v] si to[u] = to[v] = node => u si v nu pot fi alesi in acelasi timp
  // costurile sunt disincte 2 cate 2 deci putem retine intervalul pe care este valabil un cost
  // aflam submultimea de intervale disjuncte de suma de dp maxima
  
  sort(E, E + numEvents);

  for (int i = 0; i < numEvents; i++) {
    int lo = -1, hi = i;
    while (hi - lo > 1) {
      int mid = (lo + hi) >> 1;
      if (E[mid].e < E[i].b)
        lo = mid;
      else
        hi = mid;
    }
    if ((lo == -1) || (eventDp[i - 1] > eventDp[lo] + E[i].cost)) {
      if (eventDp[i - 1] > E[i].cost)
        eventDp[i] = eventDp[i - 1];
      else
        eventDp[i] = E[i].cost;
    }
    else
      eventDp[i] = eventDp[lo] + E[i].cost;
  }
  dp[node] = eventDp[numEvents - 1] + 1;
}

int main() {
  freopen("guvern.in", "r", stdin);
  freopen("guvern.out", "w", stdout);

  int n;
  scanf("%d", &n);

  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d%d", &u, &v);
    adj[u].emplace_back(v);
    adj[v].emplace_back(u);
  }
  adj[0].emplace_back(1);

  cost[0] = 0x3f3f3f3f;
  for (int i = 1; i <= n; i++)
    scanf("%d", cost + i);

  getBounds(0);
  dfs(0);

  printf("%d\n", dp[0] - 1);

  return 0;
}