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

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

/*
客がくる順番に注文を処理
客の注文は、もっとも時間がかかる料理から処理
おなじ時間の場合は、料理のindexが小さい方を先に処理
また、ある料理を調理開始する際,
キューに同じ料理があれば、同時に料理する
ただし同時に料理可能な量は限られる
*/
struct Dish {
  string name;
  int time;
  int limit;
  int orderTime;
  // 料理のidx
  int idx;
  // 注文した客のidx
  int whois;
  int ordNum;
  // かかる時間が長い順番でソート
  // 同じならidxで小さい順番にソート
  bool operator<(const Dish &dh) const {
    if (dh.orderTime > this->orderTime)
      return true;
    else if (dh.orderTime < this->orderTime)
      return false;
    else if (dh.time < this->time)
      return true;
    else if (dh.time > this->time)
      return false;
    else if (dh.idx > this->idx)
      return true;
    else if (dh.idx < this->idx)
      return false;
    // さらに同じなら、注文した客のidx順で取る
    else if (dh.whois > this->whois)
      return true;
    else if (dh.whois < this->whois)
      return false;
    return dh.ordNum < this->ordNum;
  }
};

/*
{客が到着,
料理終了,
料理開始}
のイベントを登録
優先順位はこの順番で
*/
struct Event {
  int time;
  // 料理の種類
  int idx;
  // kind=0 -> 客が到着,kind=1 -> 料理終了
  // kind=2 -> 料理開始
  int kind;
  // どの客の料理か
  vector<int> who;
  // 時間の小さい方を優先
  // 同じならば,優先順位が高いeventを優先
  bool operator<(const Event &e) const {
    if (e.time < this->time)
      return true;
    else if (e.time > this->time)
      return false;
    return (e.kind < this->kind);
  }
};

// 料理は客の頼んだ順番に関係なく
// 今登録されている料理の情報に依存して決定される
set<Dish> waitDish;
int N, M;
Dish ds[101];
map<string, int> ms;
int T[101];
int K[101];
int leftDish[101];
int finTimes[101];
bool need[100001];
vector<string> order[101];

int main() {
  bool fst = true;
  while (cin >> N >> M && (N | M)) {
    if (fst)
      fst = false;
    else
      cout << endl;
    waitDish.clear();
    ms.clear();
    for (int i = 0; i < N; i++) {
      cin >> ds[i].name >> ds[i].limit >> ds[i].time;
      ms[ds[i].name] = i;
      ds[i].idx = i;
    }
    for (int i = 0; i < M; i++) {
      order[i].clear();
      cin >> T[i];
      cin >> K[i];
      // 残りの料理量
      leftDish[i] = K[i];
      for (int j = 0; j < K[i]; j++) {
        string str;
        cin >> str;
        order[i].push_back(str);
      }
    }
    // 料理終了時か,客到着時に料理を開始
    priority_queue<Event> pq;
    bool isCook = false;
    // 客到着イベント登録
    for (int i = 0; i < M; i++) {
      Event e;
      e.kind = 0;
      e.idx = i;
      e.time = T[i];
      pq.push(e);
    }
    while (pq.size()) {
      Event e = pq.top();
      pq.pop();
      // 客到着
      if (e.kind == 0) {
        // 料理を登録
        for (int j = 0; j < K[e.idx]; j++) {
          int dk = ms[order[e.idx][j]];
          Dish tmp = ds[dk];
          tmp.whois = e.idx;
          tmp.orderTime = e.time;
          tmp.ordNum = j;
          waitDish.insert(tmp);
        }
        // 料理開始イベントを登録
        Event ne;
        ne.time = e.time;
        ne.kind = 2;
        pq.push(ne);
      }
      // 料理終了
      else if (e.kind == 1) {
        // 料理の種類
        int dkind = e.idx;
        // 登録してある料理を終了させる
        for (int i = 0; i < e.who.size(); i++) {
          // ユーザのid
          int user = e.who[i];
          leftDish[user]--;
          // 注文終了時間を登録
          if (leftDish[user] == 0) {
            finTimes[user] = e.time;
          }
        }
        isCook = false;
        // 料理開始イベントを登録
        Event ne;
        ne.time = e.time;
        ne.kind = 2;
        pq.push(ne);
      }
      // 料理開始
      else {
        // すでに料理を開始している
        // または待ち料理が存在しない
        if (isCook || waitDish.size() == 0)
          continue;
        isCook = true;
        Dish d = *(waitDish.begin());
        int lim = (waitDish.begin())->limit;
        Event ne;
        ne.kind = 1;
        ne.idx = d.idx;
        ne.time = e.time + (waitDish.begin())->time;
        vector<Dish> tmp;
        for (set<Dish>::iterator it = waitDish.begin(); it != waitDish.end();
             it++) {
          tmp.push_back(*it);
        }
        vector<int> idxs;
        for (int i = 0; i < tmp.size(); i++) {
          if (lim > 0 && tmp[i].idx == d.idx) {
            ne.who.push_back(tmp[i].whois);
            lim--;
          } else
            idxs.push_back(i);
        }
        waitDish.clear();
        for (int i = 0; i < idxs.size(); i++) {
          int cur = idxs[i];
          waitDish.insert(tmp[cur]);
        }
        //// limが0になるまで
        // ne.who.push_back(waitDish.begin()->whois);
        // lim--;
        // waitDish.erase(waitDish.begin());
        // for(set<Dish>::iterator it=waitDish.begin();it!=waitDish.end();it++){
        //     if(lim==0)break;
        //     // 同じ料理ならば、登録
        //     if(it->idx==d.idx){
        //         ne.who.push_back(it->whois);
        //         lim--;
        //         waitDish.erase(it);
        //         it=waitDish.begin();
        //     }
        // }
        //// イベントを登録
        pq.push(ne);
      }
    }
    // 終了時間を表示
    for (int i = 0; i < M; i++)
      cout << finTimes[i] << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <vector>

using namespace std;

/*
客がくる順番に注文を処理
客の注文は、もっとも時間がかかる料理から処理
おなじ時間の場合は、料理のindexが小さい方を先に処理
また、ある料理を調理開始する際,
キューに同じ料理があれば、同時に料理する
ただし同時に料理可能な量は限られる
*/
struct Dish {
  string name;
  int time;
  int limit;
  int orderTime;
  // 料理のidx
  int idx;
  // 注文した客のidx
  int whois;
  int ordNum;
  // かかる時間が長い順番でソート
  // 同じならidxで小さい順番にソート
  bool operator<(const Dish &dh) const {
    if (dh.orderTime > this->orderTime)
      return true;
    else if (dh.orderTime < this->orderTime)
      return false;
    else if (dh.time < this->time)
      return true;
    else if (dh.time > this->time)
      return false;
    else if (dh.idx > this->idx)
      return true;
    else if (dh.idx < this->idx)
      return false;
    // さらに同じなら、注文した客のidx順で取る
    else if (dh.whois > this->whois)
      return true;
    else if (dh.whois < this->whois)
      return false;
    return dh.ordNum < this->ordNum;
    // return dh.whois>this->whois;
  }
};

/*
{客が到着,
料理終了,
料理開始}
のイベントを登録
優先順位はこの順番で
*/
struct Event {
  int time;
  // 料理の種類
  int idx;
  // kind=0 -> 客が到着,kind=1 -> 料理終了
  // kind=2 -> 料理開始
  int kind;
  // どの客の料理か
  vector<int> who;
  // 時間の小さい方を優先
  // 同じならば,優先順位が高いeventを優先
  bool operator<(const Event &e) const {
    if (e.time < this->time)
      return true;
    else if (e.time > this->time)
      return false;
    return (e.kind < this->kind);
  }
};

// 料理は客の頼んだ順番に関係なく
// 今登録されている料理の情報に依存して決定される
set<Dish> waitDish;
int N, M;
Dish ds[101];
map<string, int> ms;
int T[101];
int K[101];
int leftDish[101];
int finTimes[101];
vector<string> order[101];

int main() {
  while (cin >> N >> M && (N | M)) {
    waitDish.clear();
    ms.clear();
    for (int i = 0; i < N; i++) {
      cin >> ds[i].name >> ds[i].limit >> ds[i].time;
      ms[ds[i].name] = i;
      ds[i].idx = i;
    }
    for (int i = 0; i < M; i++) {
      order[i].clear();
      cin >> T[i];
      cin >> K[i];
      // 残りの料理量
      leftDish[i] = K[i];
      for (int j = 0; j < K[i]; j++) {
        string str;
        cin >> str;
        order[i].push_back(str);
      }
    }
    // 料理終了時か,客到着時に料理を開始
    priority_queue<Event> pq;
    bool isCook = false;
    // 客到着イベント登録
    for (int i = 0; i < M; i++) {
      Event e;
      e.kind = 0;
      e.idx = i;
      e.time = T[i];
      pq.push(e);
    }
    while (pq.size()) {
      Event e = pq.top();
      pq.pop();
      // 客到着
      if (e.kind == 0) {
        if (e.idx == 1) {
          //          cout<<endl;
        }
        // 料理を登録
        for (int j = 0; j < K[e.idx]; j++) {
          int dk = ms[order[e.idx][j]];
          Dish tmp = ds[dk];
          tmp.whois = e.idx;
          tmp.orderTime = e.time;
          tmp.ordNum = j;
          waitDish.insert(tmp);
        }
        // 料理開始イベントを登録
        Event ne;
        ne.time = e.time;
        ne.kind = 2;
        pq.push(ne);
      }
      // 料理終了
      else if (e.kind == 1) {
        // 料理の種類
        int dkind = e.idx;
        // 登録してある料理を終了させる
        for (int i = 0; i < e.who.size(); i++) {
          // ユーザのid
          int user = e.who[i];
          leftDish[user]--;
          // 注文終了時間を登録
          if (leftDish[user] == 0) {
            finTimes[user] = e.time;
          }
        }
        isCook = false;
        // 料理開始イベントを登録
        Event ne;
        ne.time = e.time;
        ne.kind = 2;
        pq.push(ne);
      }
      // 料理開始
      else {
        // すでに料理を開始している
        // または待ち料理が存在しない
        if (isCook || waitDish.size() == 0)
          continue;
        isCook = true;
        Dish d = *(waitDish.begin());
        int lim = (waitDish.begin())->limit;
        Event ne;
        ne.kind = 1;
        ne.idx = d.idx;
        ne.time = e.time + (waitDish.begin())->time;
        // limが0になるまで
        ne.who.push_back(waitDish.begin()->whois);
        lim--;
        waitDish.erase(waitDish.begin());
        for (set<Dish>::iterator it = waitDish.begin(); it != waitDish.end();
             it++) {
          if (lim == 0)
            break;
          // 同じ料理ならば、登録
          if (it->idx == d.idx) {
            ne.who.push_back(it->whois);
            lim--;
            waitDish.erase(it);
            it = waitDish.begin();
          }
        }
        // while(lim>0&&waitDish.size()&&waitDish.begin()->idx==d.idx){
        //     // 客のidを登録
        //     ne.who.push_back((waitDish.begin())->whois);
        //     // 今回の料理を削除
        //     waitDish.erase(waitDish.begin());
        // }
        //  イベントを登録
        pq.push(ne);
      }
    }
    // 終了時間を表示
    for (int i = 0; i < M; i++)
      cout << finTimes[i] << endl;
  }
  return 0;
}