What Really Happened on Mars?

Simulate a real-time task scheduler under the priority ceiling protocol and print the finish time of each task.

Medium7SimulationGreedyImplementationGraphNo attempts yetTime limit2sMemory limit512 MB

Problem

The real-time software of the Mars Pathfinder spacecraft ran into a fault called priority inversion. One way to deal with it is the priority ceiling protocol.

In this problem you simulate several tasks executing under that protocol. The tasks share a set of resources, and each resource is used by at most one task at a time. To enforce this, a task locks a resource before it uses the resource and unlocks it afterwards. Each task is given a start time, a base priority that no other task shares, and a sequence of instructions. Each task also has a current priority, which may change while the task runs. There are three kinds of instructions:

  • compute, performs one microsecond of computation
  • lock kk, locks resource kk (this takes no processor time)
  • unlock kk, unlocks resource kk (this takes no processor time)

After locking a resource, a task owns that resource until the task unlocks it. A task unlocks only the owned resource it locked most recently, never locks a resource it already owns, and owns no resource when it finishes.

Every resource has a fixed priority ceiling, the largest base priority among the tasks whose instruction sequence contains an instruction locking that resource.

One processor executes the tasks. When the processor starts, it sets its clock to zero and then repeats the following steps forever.

Step 1. Identify the running tasks. A task is running if its start time is at most the current clock value and not all of its instructions have been executed.

Step 2. Determine the current priority of every running task and which of the running tasks are blocked. A running task TT is blocked if the next instruction of TT locks resource kk and either resource kk is already owned, or at least one other task owns a resource \ell whose priority ceiling is greater than or equal to the current priority of TT. In that case every task owning such a kk or \ell blocks TT. The current priority of a task TT is the maximum of the base priority of TT and the current priorities of all tasks that TT blocks.

Step 3. Execute the next instruction of the non-blocked running task with the highest current priority, if such a task exists. If there was no such task, or if a compute instruction was executed, increase the clock by one microsecond. If a lock or an unlock instruction was executed, leave the clock unchanged.

The protocol above has the following properties.

  • The current priority is defined from current priorities and from blocking, and blocking is defined from current priorities. The definition looks circular, but exactly one set of current priorities satisfies it.
  • Every task eventually finishes.
  • Step 3 never produces a tie.

Input

The first line contains two integers tt (1t201 \le t \le 20), the number of tasks, and rr (1r201 \le r \le 20), the number of resources. Each of the next tt lines describes one task, the ii-th of these lines describing task ii. A task description begins with three integers, the start time ss (1s100001 \le s \le 10000), the base priority bb (1bt1 \le b \le t), and a count aa (1a1001 \le a \le 100). It ends with aa strings that describe the instructions. Each string is a letter (C or L or U) followed by an integer. The string Cnn (1n1001 \le n \le 100) stands for nn compute instructions in a row. The strings Lkk and Ukk (1kr1 \le k \le r) stand for the instruction locking resource kk and the instruction unlocking resource kk.

No two tasks have the same base priority.

Output

For each task, print the time at which it finishes execution, in the order the tasks are given in the input.