Problem p02788 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <algorithm>
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

#define ll long long
#define loop(__x, __start, __end) for (int __x = __start; __x < __end; __x++)

struct Monster {
  ll x, h;
  bool operator<(const Monster &other) const { return x < other.x; }
};

#define MAX_X 1000000000LL
#define INFTY 1e9
ll N, D, E;
vector<Monster> M;

// 1)
// 0 1 2 3 4 5 6 7 8 9
//   2       4       2
//       - - - o - - -
//   - - - o - - -
//
// 2)
// 1 2 3 4 5 6 7 8 9
// 5 4 3 2 1 2 3 4 5
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 3   3   3   3   3     3     3     3
// - - o - -
// - - o - -
// - - o - -

vector<ll> A, B;

void init() {
  // Nを2の累乗に補正
  ll n = 1;
  while (n < N)
    n *= 2;
  N = n;
  A = vector<ll>(N * 2 - 1, 0);
  B = vector<ll>(N * 2 - 1, 0);
}

void addRec(ll a, ll b, ll val, ll n, ll l, ll r) {
  // a l r b
  if (a <= l && r <= b) {
    A.at(n) += val;
    return;
  }

  // l  a  r    b
  if (l < b && a < r) {
    B.at(n) += (min(b, r) - max(a, l)) * val;
    addRec(a, b, val, n * 2 + 1, l, (l + r) / 2);
    addRec(a, b, val, n * 2 + 2, (l + r) / 2, r);
  }
}

void add(ll a, ll b, ll val) { addRec(a, b, val, 0, 0, N); }

ll findRec(ll x, ll y, ll n, ll l, ll r) {
  // i)        l      r    x   y
  // i)  x   y l      r
  if (r <= x || y <= l)
    return 0;
  // iii)  x    l     r    y
  if (x <= l && r <= y) {
    return A.at(n) * (r - l) + B.at(n);
  }
  // iv)   x    l    y   r
  ll res = (min(y, r) - max(x, l)) * A.at(n);
  res += findRec(x, y, n * 2 + 1, l, (l + r) / 2);
  res += findRec(x, y, n * 2 + 2, (l + r) / 2, r);
  return res;
}

ll find(ll x, ll y) { return findRec(x, y, 0, 0, N); }

void dumpRec(ll n, int depth) {
  if (n >= A.size())
    return;
  for (int i = 0; i < depth; i++)
    cout << "\t";
  cout << "(" << n << ", " << A.at(n) << ", " << B.at(n) << ")" << endl;
  dumpRec(n * 2 + 1, depth + 1);
  dumpRec(n * 2 + 2, depth + 1);
}

void dump() {
  cout << "====== dump =======" << endl;
  dumpRec(0, 0);
}

void input() {
  cin >> N >> D >> E;
  ll x, h;
  for (int i = 0; i < N; i++) {
    cin >> x >> h;
    M.push_back({x, h});
  }
}

void solve() {
  init();

  sort(M.begin(), M.end());
  ll total = 0;

  // 10^5
  for (ll i = 0; i < M.size(); i++) {
    auto &m = M.at(i);
    // log{10^5}
    ll h = m.h - find(i, i + 1);
    if (h <= 0)
      continue;
    ll count = ceil((double)h / E);
    total += count;
    ll max_x = min(m.x + 2 * D, MAX_X);
    ll max_j = i;
    while (max_j < M.size() && M.at(max_j).x <= max_x)
      max_j++;
    add(i, max_j, count * E);
  }

  cout << total << endl;
}

int main() {
  input();
  solve();
  return 0;
}


Fixed submission:
#include <algorithm>
#include <iostream>
#include <math.h>
#include <vector>
using namespace std;

#define ll long long
#define loop(__x, __start, __end) for (int __x = __start; __x < __end; __x++)

struct Monster {
  ll x, h;
  bool operator<(const Monster &other) const { return x < other.x; }
};

#define MAX_X 1000000000LL
#define INFTY 1e9
ll N, D, E;
vector<Monster> M;

// 1)
// 0 1 2 3 4 5 6 7 8 9
//   2       4       2
//       - - - o - - -
//   - - - o - - -
//
// 2)
// 1 2 3 4 5 6 7 8 9
// 5 4 3 2 1 2 3 4 5
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// - - - - o - - - -
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 3   3   3   3   3     3     3     3
// - - o - -
// - - o - -
// - - o - -

vector<ll> A, B;

void init() {
  // Nを2の累乗に補正
  ll n = 1;
  while (n < N)
    n *= 2;
  N = n;
  A = vector<ll>(N * 2 - 1, 0);
  B = vector<ll>(N * 2 - 1, 0);
}

void addRec(ll a, ll b, ll val, ll n, ll l, ll r) {
  // a l r b
  if (a <= l && r <= b) {
    A.at(n) += val;
    return;
  }

  // l  a  r    b
  if (l < b && a < r) {
    B.at(n) += (min(b, r) - max(a, l)) * val;
    addRec(a, b, val, n * 2 + 1, l, (l + r) / 2);
    addRec(a, b, val, n * 2 + 2, (l + r) / 2, r);
  }
}

void add(ll a, ll b, ll val) { addRec(a, b, val, 0, 0, N); }

ll findRec(ll x, ll y, ll n, ll l, ll r) {
  // i)        l      r    x   y
  // i)  x   y l      r
  if (r <= x || y <= l)
    return 0;
  // iii)  x    l     r    y
  if (x <= l && r <= y) {
    return A.at(n) * (r - l) + B.at(n);
  }
  // iv)   x    l    y   r
  ll res = (min(y, r) - max(x, l)) * A.at(n);
  res += findRec(x, y, n * 2 + 1, l, (l + r) / 2);
  res += findRec(x, y, n * 2 + 2, (l + r) / 2, r);
  return res;
}

ll find(ll x, ll y) { return findRec(x, y, 0, 0, N); }

void dumpRec(ll n, int depth) {
  if (n >= A.size())
    return;
  for (int i = 0; i < depth; i++)
    cout << "\t";
  cout << "(" << n << ", " << A.at(n) << ", " << B.at(n) << ")" << endl;
  dumpRec(n * 2 + 1, depth + 1);
  dumpRec(n * 2 + 2, depth + 1);
}

void dump() {
  cout << "====== dump =======" << endl;
  dumpRec(0, 0);
}

void input() {
  cin >> N >> D >> E;
  ll x, h;
  for (int i = 0; i < N; i++) {
    cin >> x >> h;
    M.push_back({x, h});
  }
}

void solve() {
  init();

  sort(M.begin(), M.end());
  ll total = 0;

  // 10^5
  for (ll i = 0; i < M.size(); i++) {
    auto &m = M.at(i);
    // log{10^5}
    ll h = m.h - find(i, i + 1);
    if (h <= 0)
      continue;
    ll count = ceil((double)h / E);
    total += count;
    ll max_x = min(m.x + 2 * D, MAX_X);
    ll max_j =
        upper_bound(M.begin() + i, M.end(), (Monster){max_x, 0}) - M.begin();
    add(i, max_j, count * E);
  }

  cout << total << endl;
}

int main() {
  input();
  solve();
  return 0;
}