Problem:
Problem B: Restaurant

Steve runs a small restaurant in a city. Also, as he is the only cook in his restaurant, he cooks everything
ordered by customers.

Basically he attends to orders by first-come-first-served principle. He takes some prescribed time to
prepare each dish. As a customer can order more than one dish at a time, Steve starts his cooking with
the dish that takes the longest time to prepare. In case that there are two or more dishes that take
the same amount of time to prepare, he makes these dishes in the sequence as listed in the menu card
of his restaurant. Note that he does not care in which order these dishes have been ordered. When he
completes all dishes ordered by a customer, he immediately passes these dishes to the waitress and has
them served to the customer. Time for serving is negligible.

On the other hand, during his cooking for someone’s order, another customer may come and order dishes.
For his efficiency, he decided to prepare together multiple dishes of the same if possible. When he starts
cooking for new dishes, he looks over the orders accepted by that time (including the order accepted
exactly at that time if any), and counts the number of the same dishes he is going to cook next. Time
required for cooking is the same no matter how many dishes he prepare at once. Unfortunately, he has
only limited capacity in the kitchen, and hence it is sometimes impossible that the requested number of
dishes are prepared at once. In such cases, he just prepares as many dishes as possible.

Your task is to write a program that simulates the restaurant. Given a list of dishes in the menu card
and orders from customers with their accepted times, your program should output a list of times when
each customer is served.

Input

The input contains multiple data sets. Each data set is in the format below:

N M
Name1 Limit1 Time1
...
NameN LimitN TimeN
T1 K1 Dish1,1 . . . Dish1,K1
...
TM KM DishM,1 . . . DishM,KM

Here, N (1 ≤ N ≤ 20) and M (1 ≤ M ≤ 100) specify the number of entries in the menu card and the
number of orders that Steve will receive, respectively; each Namei is the name of a dish of the i-th entry
in the menu card, which consists of up to 20 alphabetical letters; Limiti (1 ≤ Limiti ≤ 10) is the number of dishes he can prepare at the same time; Timei (1 ≤ Timei ≤ 1000) is time required to prepare a dish
(or dishes) of the i-th entry; Tj (1 ≤ Tj ≤ 10000000) is the time when the j-th order is accepted; Kj
(1 ≤ Kj ≤ 10) is the number of dishes in the j-th order; and each Dishj,k represents a dish in the j-th
order.

You may assume that every dish in the orders is listed in the menu card, but you should note that each
order may contain multiple occurrences of the same dishes. The orders are given in ascending order by
Tj , and no two orders are accepted at the same time.

The input is terminated with a line that contains two zeros. This is not part of data sets and hence
should not be processed.

Output

Your program should produce the output of M -lines for each data set. The i-th line of the output should
contain a single integer that indicates the time when the i-th order will be completed and served to the
customer.

Print a blank line between two successive data sets.

Sample Input

5 4
Ramen 3 10
Chahan 5 5
Gyoza 5 10
Rice 1 1
Soup 1 1
5 2 Ramen Gyoza
10 6 Chahan Gyoza Soup Ramen Gyoza Rice
20 1 Chahan
25 1 Ramen
0 0

Output for the Sample Input

25
42
40
35

Solution in C++ (judge verdict: Accepted)

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
struct Event{
  // type 0 - order
  // type 1 - complete
  int type, time, dish, customer;
  Event(int ty, int t, int d, int c):
    type(ty), time(t), dish(d), customer(c) {}
  bool operator < (const Event& e) const {
    if(time != e.time) return time > e.time;
    if(type != e.type) return type > e.type;
    return dish > e.dish;
  }
};
struct Dish{
  string name;
  int limit, time;
  Dish() {}
  bool operator < (const Dish& d) const {
    return time > d.time;
  }
};

int main(){
  int N, M;
  bool first = true;
  while(cin >> N >> M && N){
    if(first) first = false;
    else cout << endl;
    vector<Dish> dishes(N);
    REP(i, N) cin >> dishes[i].name >> dishes[i].limit >> dishes[i].time;
    stable_sort(dishes.begin(), dishes.end());
    map<string, int> name_to_index;
    REP(i, N) name_to_index[dishes[i].name] = i;
    priority_queue<Event> que;
    REP(i, M){
      int T, K; cin >> T >> K;
      REP(j, K){
        string name; cin >> name;
        que.push(Event(0, T, name_to_index[name], i));
      }
    }
    vector<int> answer(M);
    vector<Event> cook_queue;
    int cooking = 0;
    while(!que.empty()){
      Event e = que.top(); que.pop();
      if(e.type == 0){
        //printf("customer %d order %s : time %d\n", e.customer, dishes[e.dish].name.c_str(), e.time);
        cook_queue.push_back(Event(0, 0, e.dish, e.customer));
      }else if(e.type == 1){
        //printf("customer %d's %s is finshed: time %d\n", e.customer, dishes[e.dish].name.c_str(), e.time);
        cooking --;
        answer[e.customer] = e.time;
      }
      if(cooking == 0 && !cook_queue.empty() && (que.empty() || e.time != que.top().time)){
        // new dish
        int new_dish = cook_queue[0].dish;
        for(vector<Event>::iterator it = cook_queue.begin(); it != cook_queue.end(); ){
          if(it->dish == new_dish){
            //printf("customer %d's %s is started : time %d -> %d\n", it->customer, dishes[it->dish].name.c_str(), e.time, e.time + dishes[new_dish].time);
            que.push(Event(1, e.time + dishes[new_dish].time, it->dish, it->customer));
            cooking++;
            it = cook_queue.erase(it);
            if(cooking >= dishes[new_dish].limit) break;
          }else{
            it++;
          }
        }
        assert(cooking <= dishes[new_dish].limit);
      }
    }
    assert(cooking == 0);
    REP(i, M) cout << answer[i] << endl;
  }
  return 0;
}