Submission #1086464

#TimeUsernameProblemLanguageResultExecution timeMemory
1086464vjudge1Fireworks (APIO16_fireworks)C++17
100 / 100
203 ms102724 KiB
#include <iostream>
#include <map>
#include <utility>
#include <vector>

struct ConvexLinearSet {
  int m = 0;
  long long c = 0;
  std::map<long long, int> m_changes; // key: xpos, val: dm

  int size() {
    return m_changes.size();
  }
  
  void merge_with(const ConvexLinearSet& o) {
    m += o.m;
    c += o.c;
    for (auto [x, dm]: o.m_changes) {
      m_changes[x] += dm;
    }
  }

  long long query_min() {
    long long x;
    int dm;
    auto it = m_changes.rbegin();
    while (it != m_changes.rend() && m >= 0) {
      std::tie(x, dm) = *it;

      // update current m & c
      // m*x + c = (m - dm)*x + new_c -> new_c = x*dm + c
      m -= dm;
      c += x * dm;
      it++;
    }

    return x * m + c;
  }

  void apply_w(int w) {
    long long x, x_prev, xprev2;
    int dm;
    while (!m_changes.empty() && m >= 0) {
      // pop largest
      x_prev = x;
      std::tie(x, dm) = *m_changes.rbegin();
      m_changes.erase(x);

      // update current m & c
      // m*x + c = (m - dm)*x + new_c -> new_c = x*dm + c
      m -= dm;
      c += x * dm;
    }

    bool has_zero_grad = (m == -dm);
    long long minval = x * m + c;
    // std::cerr << "minimum at m=" << m << " x=" << x << " val=" << minval << std::endl;

    if (m != -1) {
      m_changes[x] -= m + 1;
    }

    m_changes[x + w]++; // make next grad = 0 here

    // we are at m = 0 now, let's jump to the end of m = 0
    x = has_zero_grad ? x_prev : x;
    x += w;

    // make next_m = 1
    // const = x + new_c -> new_c = const - x
    m_changes[x]++;
    m = 1;
    c = minval - x;
  }

  void debug() {
    std::cerr << "{\n";
    int cur_m = m;
    long long cur_c = c;
    for (auto it = m_changes.rbegin(); it != m_changes.rend(); it++) {
      long long x;
      int dm;
      std::tie(x, dm) = *it;
      std::cerr << "  y = (" << cur_m << ")x + (" << cur_c << ") from x >= " << x << '\n';
      cur_m -= dm;
      cur_c += x * dm;
    }
    std::cerr << "  y = (" << cur_m << ")x + (" << cur_c << ") otherwise\n";
    std::cerr << "}\n";

    std::cerr << "changes:"; for (auto [x, dm]: m_changes) std::cerr << " (x=" << x << ",d=" << dm << ")"; std::cerr << std::endl;
  }
};

int main() {
  std::cin.tie(NULL)->sync_with_stdio(false);

  int n, m;
  std::cin >> n >> m;

  std::vector<ConvexLinearSet> sets(n + m + 1);
  std::vector<std::vector<int>> adj(n + m + 1);
  std::vector<int> w(n + m + 1);
  w[1] = 0;
  for (int i = 2; i <= n + m; i++) {
    int par;
    std::cin >> par >> w[i];

    adj[par].push_back(i);
    if (i > n) {
      // leaf nodes
      sets[i].m = 1;
      sets[i].c = -w[i];
      sets[i].m_changes[w[i]] = 2;
    }
  }

  auto dfs = [&](auto &&dfs_fn, int u) -> void {
    if (adj[u].empty()) {
      // base case
      // std::cerr << "node=" << u << " w=" << w[u] << " ";
      // sets[u].debug();
      // std::cerr << std::endl;
      return;
    }

    // recursive + find largest set
    for (int v: adj[u]) {
      dfs_fn(dfs_fn, v);
      if (sets[u].size() < sets[v].size()) {
        std::swap(sets[u], sets[v]);
      }
    }

    // merge sets
    for (int v: adj[u]) {
      sets[u].merge_with(sets[v]);
    }

    sets[u].apply_w(w[u]);

    // std::cerr << "node=" << u << " w=" << w[u] << " ";
    // sets[u].debug();
    // std::cerr << std::endl;
  };

  dfs(dfs, 1);

  std::cout << sets[1].query_min() << std::endl;

  return 0;
}

Compilation message (stderr)

fireworks.cpp: In member function 'void ConvexLinearSet::apply_w(int)':
fireworks.cpp:41:26: warning: unused variable 'xprev2' [-Wunused-variable]
   41 |     long long x, x_prev, xprev2;
      |                          ^~~~~~
fireworks.cpp:45:14: warning: 'x' is used uninitialized in this function [-Wuninitialized]
   45 |       x_prev = x;
      |       ~~~~~~~^~~
fireworks.cpp:55:32: warning: 'dm' may be used uninitialized in this function [-Wmaybe-uninitialized]
   55 |     bool has_zero_grad = (m == -dm);
      |                                ^~~
fireworks.cpp:67:7: warning: 'x_prev' may be used uninitialized in this function [-Wmaybe-uninitialized]
   67 |     x += w;
      |     ~~^~~~
fireworks.cpp: In function 'int main()':
fireworks.cpp:37:14: warning: 'x' may be used uninitialized in this function [-Wmaybe-uninitialized]
   37 |     return x * m + c;
      |            ~~^~~
fireworks.cpp:24:15: note: 'x' was declared here
   24 |     long long x;
      |               ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...