ICPC 2016 - M. What Really Happened on Mars?
State the problem in your own words. Focus on the mathematical or algorithmic core rather than repeating the full statement.
Source-first archive entry
This page is built from the copied files in competitive_programming/icpc/2016/M-what-really-happened-on-mars. Edit
competitive_programming/icpc/2016/M-what-really-happened-on-mars/solution.tex to update the written solution and
competitive_programming/icpc/2016/M-what-really-happened-on-mars/solution.cpp to update the implementation.
The website does not replace those files with hand-maintained HTML. It reads the copied source tree during the build and exposes the exact files below.
Problem Statement
Copied statement text kept beside the solution archive for direct reference.
Problem M
What Really Happened on Mars?
Time limit: 2 seconds
Real-time software in the Mars Pathfinder spacecraft suffered from an issue known as priority inversion.
One technique to address this issue is to use the Priority Ceiling Protocol.
In this problem, you will simulate the execution of multiple tasks according to this protocol. The tasks
share a collection of resources, each of which can be used by only one task at a time. To ensure this,
resources must be locked before use and unlocked after use. Each task is defined by a start time, a unique
base priority, and a sequence of instructions. Each task also has a current priority, which may change
during execution. Instructions come in three types:
• compute – perform a computation for one microsecond
• lock k – lock resource k (which takes no processor time)
• unlock k – unlock resource k (which takes no processor time)
After locking a resource, a task is said to own the resource until the task unlocks it. A task will unlock
only the owned resource it most recently locked, will not lock a resource it already owns, and will
complete with no owned resources.
Each resource has a fixed priority ceiling, which is the highest base priority of any task that contains an
instruction to lock that resource.
There is a single processor that executes the tasks. When the processor starts, it initializes its clock to
zero and then runs an infinite loop with the following steps:
Step 1. Identify running tasks. A task is running if its start time is less than or equal to the current
processor clock and not all of its instructions have been executed.
Step 2. Determine the current priorities of the running tasks and which of the running tasks are blocked.
A running task T is blocked if the next instruction in T is to lock resource k and either resource k
is already owned or at least one other task owns a resource ` whose priority ceiling is greater than
or equal to the current priority of T . If T is blocked, it is said to be blocked by every task owning
such k or `. The current priority of a task T is the maximum of T ’s base priority and the current
priorities of all tasks that T blocks.
Step 3. Execute the next instruction of the non-blocked running task (if any) with the highest current
priority. If there was no such task or if a compute instruction was executed, increment the proces-
sor clock by one microsecond. If a lock or unlock instruction was executed, do not increment the
clock.
The Priority Ceiling Protocol defined above has the following properties:
• Current priority is defined in terms of current priority and blocking, and blocking is defined in
terms of current priority. While this may appear circular, there will always be a unique set of
current priorities that satisfy the definitions.
• All tasks will eventually complete.
• There will never be a tie in step 3.
Input
The first line of the input contains two integers t (1 ≤ t ≤ 20), which is the number of tasks, and
r (1 ≤ r ≤ 20), which is the number of resources. This is followed by t lines, where the ith of
these lines describes task i. The description of a task begins with three integers: the task’s start time s
(1 ≤ s ≤ 10 000), its base priority b (1 ≤ b ≤ t), and an integer a (1 ≤ a ≤ 100). A task description
is concluded by a sequence of a strings describing the instructions. Each string is a letter (C or L or U)
followed by an integer. The string Cn (1 ≤ n ≤ 100) indicates a sequence of n compute instructions.
The strings Lk and Uk (1 ≤ k ≤ r) indicate instructions locking and unlocking resource k respectively.
No two tasks have the same base priority.
Output
For each task, display the time it completes execution, in the same order that the tasks are given in the
input.
Sample Input 1 Sample Output 1
3 1 106
50 2 5 C1 L1 C1 U1 C1 107
1 1 5 C1 L1 C100 U1 C1 71
70 3 1 C1
Sample Input 2 Sample Output 2
3 3 8
5 3 5 C1 L1 C1 U1 C1 15
3 2 9 C1 L2 C1 L3 C1 U3 C1 U2 C1 16
1 1 9 C1 L3 C3 L2 C1 U2 C1 U3 C1
Editorial
Rendered from the copied solution.tex file. The original TeX source remains
available below.
Key Observations
Write the structural observations that make the problem tractable.
State any useful invariant, monotonicity property, graph interpretation, or combinatorial reformulation.
If the constraints matter, explain exactly which part of the solution they enable.
Algorithm
Describe the data structures and the state maintained by the algorithm.
Explain the processing order and why it is sufficient.
Mention corner cases explicitly if they affect the implementation.
Correctness Proof
We prove that the algorithm returns the correct answer.
Lemma 1.
State the first key claim.
Proof.
Provide a concise proof.
Lemma 2.
State the next claim if needed.
Proof.
Provide a concise proof.
Theorem.
The algorithm outputs the correct answer for every valid input.
Proof.
Combine the lemmas and finish the argument.
Complexity Analysis
State the running time and memory usage in terms of the input size.
Implementation Notes
Mention any non-obvious implementation detail that is easy to get wrong.
Mention numeric limits, indexing conventions, or tie-breaking rules if relevant.
Code
Exact copied C++ implementation from solution.cpp.
#include <bits/stdc++.h>
using namespace std;
namespace {
void solve() {
// Fill in the full solution logic for the problem here.
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
Source Files
Exact copied source-of-truth files. Edit solution.tex for the write-up and solution.cpp for the implementation.
\documentclass[11pt]{article}
\usepackage[margin=1in]{geometry}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{amsmath,amssymb,amsthm}
\usepackage{enumitem}
\title{ICPC World Finals 2016\\M. What Really Happened on Mars?}
\author{}
\date{}
\begin{document}
\maketitle
\section*{Problem Summary}
State the problem in your own words. Focus on the mathematical or algorithmic core rather than repeating the full statement.
\section*{Key Observations}
\begin{itemize}[leftmargin=*]
\item Write the structural observations that make the problem tractable.
\item State any useful invariant, monotonicity property, graph interpretation, or combinatorial reformulation.
\item If the constraints matter, explain exactly which part of the solution they enable.
\end{itemize}
\section*{Algorithm}
\begin{enumerate}[leftmargin=*]
\item Describe the data structures and the state maintained by the algorithm.
\item Explain the processing order and why it is sufficient.
\item Mention corner cases explicitly if they affect the implementation.
\end{enumerate}
\section*{Correctness Proof}
We prove that the algorithm returns the correct answer.
\paragraph{Lemma 1.}
State the first key claim.
\paragraph{Proof.}
Provide a concise proof.
\paragraph{Lemma 2.}
State the next claim if needed.
\paragraph{Proof.}
Provide a concise proof.
\paragraph{Theorem.}
The algorithm outputs the correct answer for every valid input.
\paragraph{Proof.}
Combine the lemmas and finish the argument.
\section*{Complexity Analysis}
State the running time and memory usage in terms of the input size.
\section*{Implementation Notes}
\begin{itemize}[leftmargin=*]
\item Mention any non-obvious implementation detail that is easy to get wrong.
\item Mention numeric limits, indexing conventions, or tie-breaking rules if relevant.
\end{itemize}
\end{document}
#include <bits/stdc++.h>
using namespace std;
namespace {
void solve() {
// Fill in the full solution logic for the problem here.
}
} // namespace
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}