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

#include <bitset>
#include <iostream>
#include <queue>
#include <utility>
#include <vector>

using namespace std;
typedef pair<int, int> pii;

struct Customer {
  int M, L, K;
};

bool simulate(const vector<Customer> &customers, int ops, int T) {
  int N = customers.size();
  priority_queue<int, vector<int>, greater<int>> opfree;
  for (int i = 0; i < ops; ++i) {
    opfree.push(0);
  }
  bitset<1000> done;
  int doneCount = 0;
  while (!opfree.empty()) {
    int t = opfree.top();
    opfree.pop();
    int minCustomer = -1, minTime = T + 1;
    for (int i = 0; i < N; ++i) {
      if (done[i]) {
        continue;
      }
      int cycle = customers[i].L + customers[i].K;
      int nextTime = 0;
      if (t % cycle <= customers[i].L) {
        nextTime = t;
      } else {
        nextTime = (t / cycle + 1) * cycle;
      }
      if (nextTime < minTime) {
        minTime = nextTime;
        minCustomer = i;
        if (minTime == t) {
          break;
        }
      }
    }
    int doneTime = minTime + customers[minCustomer].M;
    if (doneTime > T) {
      return false;
    }
    done[minCustomer] = true;
    opfree.push(doneTime);
    if (++doneCount == N) {
      break;
    }
  }
  return true;
}

int main() {
  ios_base::sync_with_stdio(false);
  while (true) {
    int N, T;
    cin >> N >> T;
    if (N == 0 && T == 0) {
      break;
    }
    vector<Customer> customers(N);
    for (int i = 0; i < N; ++i) {
      cin >> customers[i].M;
      cin >> customers[i].L;
      cin >> customers[i].K;
    }
    int answer = 1;
    while (!simulate(customers, answer, T)) {
      ++answer;
    }
    cout << answer << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <iostream>
#include <queue>
#include <utility>
#include <vector>

using namespace std;
typedef pair<int, int> pii;

struct Customer {
  int M, L, K;
};

bool simulate(const vector<Customer> &customers, int ops, int T) {
  const int INDEX_MASK = 0x0ffff;
  const int TIME_SHIFT = 4;
  const int MODE_DONE = 0;
  const int MODE_CALL = 1;
  const int MODE_HANG = 2;
  int N = customers.size();
  priority_queue<pii, vector<pii>, greater<pii>> cq;
  priority_queue<int, vector<int>, greater<int>> wq;
  vector<bool> done(N), waiting(N);
  for (int i = 0; i < N; ++i) {
    cq.push(pii(MODE_CALL, i));
  }
  int freeOps = ops, doneCount = 0, lastTime = 0;
  while (!cq.empty()) {
    pii p = cq.top();
    int time = p.first >> TIME_SHIFT;
    int mode = p.first & ((1 << TIME_SHIFT) - 1);
    int idx = p.second;
    lastTime = time;
    if (time > T) {
      return false;
    }
    cq.pop();
    if (mode == MODE_CALL) {
      if (freeOps > 0) {
        done[idx] = true;
        cq.push(
            pii(((time + customers[idx].M) << TIME_SHIFT) | MODE_DONE, idx));
        --freeOps;
      } else {
        cq.push(
            pii(((time + customers[idx].L) << TIME_SHIFT) | MODE_HANG, idx));
        wq.push(idx);
        waiting[idx] = true;
      }
    } else if (mode == MODE_HANG) {
      if (!done[idx]) {
        cq.push(
            pii(((time + customers[idx].K) << TIME_SHIFT) | MODE_CALL, idx));
        waiting[idx] = false;
      }
    } else if (mode == MODE_DONE) {
      ++freeOps;
      if (++doneCount == N) {
        break;
      }
      while (!wq.empty()) {
        int wi = wq.top();
        wq.pop();
        if (waiting[wi]) {
          --freeOps;
          waiting[wi] = false;
          done[wi] = true;
          cq.push(
              pii(((time + customers[wi].M) << TIME_SHIFT) | MODE_DONE, wi));
          break;
        }
      }
    }
  }
  return true;
}

int main() {
  ios_base::sync_with_stdio(false);
  while (true) {
    int N, T;
    cin >> N >> T;
    if (N == 0 && T == 0) {
      break;
    }
    vector<Customer> customers(N);
    for (int i = 0; i < N; ++i) {
      cin >> customers[i].M;
      cin >> customers[i].L;
      cin >> customers[i].K;
    }
    int answer = 1;
    while (!simulate(customers, answer, T)) {
      ++answer;
    }
    cout << answer << endl;
  }
  return 0;
}