Problem p01005 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <cassert>
#include <iostream>
#include <map>
using namespace std;

typedef long long ELM;

class RMQ {
private:
  int n;
  ELM *dat;

public:
  RMQ(int _n, ELM v = 0) {
    n = 1;
    while (n < _n)
      n *= 2;
    dat = new ELM[2 * n - 1];
    for (int i = 0; i < 2 * n - 1; ++i)
      dat[i] = v;
  }

  ~RMQ() { delete[] dat; }

  ELM at(int index) const { return dat[index + n - 1]; }

  void update(int k, ELM a, bool flag = false) {
    k += n - 1;
    dat[k] = a;
    if (dat[k] >= 0)
      ;
    else {
      cerr << "dat[" << k << "]=" << dat[k] << endl;
      assert(false);
    }
    while (k) {
      k = (k - 1) / 2;
      dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2];
      assert(dat[k] >= 0);
    }
  }

  // sum of A of [a, b)
  ELM query(const int &a, const int &b, int k = 0, int l = 0, int r = 0) const {
    if (k == 0)
      r = n;

    if (r <= a || b <= l)
      return 0;

    if (a <= l && r <= b) {
      return dat[k];
    } else {
      ELM vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
      ELM vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
      return vl + vr;
    }
  }

  // sum of A of [a, b) with erase
  ELM queryE(const int &a, const int &b, int k = 0, int l = 0, int r = 0) {
    if (k == 0)
      r = n;

    if (r <= a || b <= l)
      return 0;

    if (dat[k] == 0)
      return 0;

    if (k >= n - 1) {
      if (a <= l && r <= b) {
        ELM tmp = dat[k];
        dat[k] = 0;
        return tmp;
      } else {
        return 0;
      }
    }
    ELM vl = queryE(a, b, k * 2 + 1, l, (l + r) / 2);
    ELM vr = queryE(a, b, k * 2 + 2, (l + r) / 2, r);
    dat[k] -= (vl + vr);
    return vl + vr;
  }

  int lower_bound(const ELM &v) const {
    int l = 0;
    int r = n;
    while (r - l) {
      int m = (l + r) / 2;
      if (query(0, m + 1) < v) {
        l = m + 1;
      } else {
        r = m;
      }
    }
    return l;
  }

  int upper_bound(const ELM &v) const {
    int l = 0;
    int r = n;
    while (r - l) {
      int m = (l + r) / 2;
      if (query(0, m + 1) <= v) {
        l = m + 1;
      } else {
        r = m;
      }
    }
    return l;
  }
};

int main() {
  int Q;
  ELM L;
  while (1) {
    assert(cin >> Q >> L);
    if (Q == 0 && L == 0)
      break;
    RMQ pos(Q), enemy(Q);
    int size = 0;

    while (Q--) {
      int op;
      ELM x, r;
      assert(cin >> op);
      assert(0 <= op && op <= 4);
      if (0) { // dumy

      } else if (op == 0) { // add enemy

        ELM p = L - pos.query(0, size);
        assert(p >= 0); //!
        assert(!(size != 0 && p == 0 && enemy.at(size - 1) != 0));
        pos.update(size, p);
        enemy.update(size, 1);
        size += 1;

      } else if (op == 1) { // move enemys
        assert(cin >> x);
        assert(1LL <= x && x <= 1000000000LL);
        int end = min(pos.upper_bound(x), size);
        ELM num = enemy.queryE(0, end);
        x -= pos.queryE(0, end);
        int head = pos.lower_bound(1);
        if (head < size) {
          ELM nextPos = pos.at(head) - x;
          assert(nextPos > 0); //!
          pos.update(head, nextPos);
        }
        if (num)
          cout << "damage " << num << endl;

      } else if (op == 2) { // attack x(th) enemy
        assert(cin >> x);
        assert(1LL <= x && x <= 1000000000LL);
        if (enemy.query(0, size) >= x) {
          int p = enemy.lower_bound(x);
          enemy.queryE(p, p + 1);
          cout << "hit" << endl;
        } else {
          cout << "miss" << endl;
        }

      } else if (op == 3) { // bomb enemys at x with range of r
        assert(cin >> x >> r);
        assert(0LL <= x && x <= L);
        assert(0LL <= r && r <= 1000000000LL);
        int begin = pos.lower_bound(x - r);
        int end = pos.upper_bound(x + r);
        ELM num = enemy.queryE(begin, end);
        cout << "bomb " << num << endl;

      } else if (op == 4) { // print the position of x(th) enemy
        assert(cin >> x);
        assert(1LL <= x && x <= 1000000000LL);
        if (enemy.query(0, size) >= x) {
          int p = enemy.lower_bound(x);
          cout << "distance " << pos.query(0, p + 1) << endl;
        } else {
          cout << "distance " << -1 << endl;
        }
      }
    }
    cout << "end" << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;

int main() {
  int Q, L;
  while (scanf("%d %d", &Q, &L) && (Q | L)) {
    vector<int> v;
    while (Q--) {
      int op;
      scanf("%d", &op);
      if (0) {
      } else if (op == 0) {
        v.push_back(L);
      } else if (op == 1) {
        int d;
        scanf("%d", &d);
        int damage = 0;
        for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
          *it -= d;
          if (*it <= 0) {
            ++damage;
            v.erase(it);
            --it;
          }
        }
        if (damage)
          printf("damage %d\\n", damage);
      } else if (op == 2) {
        int k;
        scanf("%d", &k);
        if (k <= v.size()) {
          printf("hit\\n");
          v.erase(v.begin() + k - 1);
        } else {
          printf("miss\\n");
        }
      } else if (op == 3) {
        int x, r;
        scanf("%d %d", &x, &r);
        vector<int>::iterator begin, end;
        begin = lower_bound(v.begin(), v.end(), x - r);
        end = upper_bound(v.begin(), v.end(), x + r);
        printf("bomb %d\\n", end - begin);
        v.erase(begin, end);
      } else if (op == 4) {
        int k;
        scanf("%d", &k);
        if (k <= v.size()) {
          printf("distance %d\\n", v[k - 1]);
        } else {
          printf("distance -1\\n");
        }
      }
    }
    printf("end\\n");
  }
  return 0;
}