CF 102569M - Notifications
Each notification arrives at a specific moment and contains a video with a given duration. Vasya always watches videos in the order their notifications arrive. If he is idle when a notification appears, he immediately starts watching that video.
Rating: -
Tags: -
Solve time: 1m 10s
Verified: yes
Solution
Problem Understanding
Each notification arrives at a specific moment and contains a video with a given duration. Vasya always watches videos in the order their notifications arrive. If he is idle when a notification appears, he immediately starts watching that video. If he is already watching something, the new video waits in the queue until every earlier unfinished video has been watched.
The input already gives notifications in non-decreasing order of arrival time, so we never need to reorder them. The task is simply to determine the finishing time of the final video after processing every notification.
The number of notifications reaches 200000, while both arrival times and durations can be as large as (10^9). Any algorithm that repeatedly simulates time or scans previously processed notifications for every new notification would perform too many operations. A linear solution is easily fast enough, while quadratic approaches are ruled out. Since finish times may exceed (2 \times 10^9), the algorithm must also avoid assumptions that values fit into 32-bit integers, although Python integers naturally handle this.
One easy mistake is forgetting that Vasya can become idle before the next notification arrives.
Example:
2
1 2
10 3
The correct answer is 13. Vasya finishes the first video at time 3, waits until time 10, then watches the second video until 13. Simply adding durations to the previous finish time would incorrectly produce 6.
Another subtle case occurs when several notifications arrive at exactly the same moment.
3
5 2
5 4
5 1
The correct answer is 12. The first video starts immediately at time 5, and the other two are appended behind it in arrival order. Treating notifications with the same timestamp as simultaneous independent events would lose that ordering.
A third case is when a notification arrives exactly as the previous video finishes.
2
1 4
5 3
The correct answer is 8. At time 5 Vasya is no longer busy, so the second video starts immediately. Using a strict comparison such as finish > arrival instead of finish >= arrival can shift the schedule incorrectly.
Approaches
A straightforward simulation keeps every waiting video in a queue. Whenever a notification arrives, the simulation advances time, removes every completed video, then either starts the arriving video immediately or appends it to the queue. This faithfully models the rules, but in the worst case each arrival may process many queued videos again. With (n) notifications, this can require (O(n^2)) work, roughly (4 \times 10^{10}) operations when (n = 200000).
The queue itself is actually unnecessary. At any moment, the only information that affects future notifications is the time when Vasya will become free. Suppose that after processing some notifications, he is guaranteed to stay busy until time finish. When a new notification arrives at time t, only two situations are possible.
If finish <= t, Vasya is idle when the notification appears. The new video starts at t and finishes at t + d.
If finish > t, Vasya is still busy. The new video starts exactly at finish and ends at finish + d.
Both situations can be expressed with one formula:
finish = max(finish, t) + d
This single variable completely captures the state of the entire watching queue, allowing every notification to be processed once.
| Approach | Time Complexity | Space Complexity | Verdict |
|---|---|---|---|
| Brute Force | O(n²) | O(n) | Too slow |
| Optimal | O(n) | O(1) | Accepted |
Algorithm Walkthrough
- Initialize
finish = 0. Before any notifications arrive, Vasya is idle. - Read notifications one by one in their given order. The input is already sorted by arrival time, so no preprocessing is needed.
- For each notification with arrival time
tand durationd, computestart = max(finish, t). If Vasya is still busy, the video waits untilfinish. Otherwise it starts immediately att. - Update
finish = start + d. This becomes the earliest moment when every processed notification has been completely watched. - After all notifications have been processed, output
finish.
Why it works
The key invariant is that after processing the first i notifications, finish equals the exact time when all of those videos have been watched. When the next notification arrives, no earlier video can start later than finish, because every previous notification has already been scheduled. If Vasya is idle, the new video begins immediately. If he is busy, every earlier video must finish before the new one can begin, so the earliest possible start is exactly finish. Updating finish with max(finish, t) + d preserves the invariant, and after the last notification it represents the completion time of the final video.
Python Solution
import sys
input = sys.stdin.readline
def solve():
n = int(input())
finish = 0
for _ in range(n):
t, d = map(int, input().split())
finish = max(finish, t) + d
print(finish)
if __name__ == "__main__":
solve()
The solution keeps only one variable, finish, which represents the end of the current schedule. Every notification updates this value using the formula derived in the algorithm.
The expression max(finish, t) handles both possible states without branching. If Vasya is already busy, the current schedule continues uninterrupted. If he has already finished everything, the schedule restarts from the notification's arrival time.
The comparison uses max rather than a strict inequality, which correctly handles notifications arriving exactly when the previous video finishes. Python integers automatically grow as needed, so even very large finish times remain safe.
Worked Examples
Example 1
Input:
5
1 4
3 3
6 1
10 2
10 3
| Notification | Arrival | Duration | Previous finish | Start | New finish |
|---|---|---|---|---|---|
| 1 | 1 | 4 | 0 | 1 | 5 |
| 2 | 3 | 3 | 5 | 5 | 8 |
| 3 | 6 | 1 | 8 | 8 | 9 |
| 4 | 10 | 2 | 9 | 10 | 12 |
| 5 | 10 | 3 | 12 | 12 | 15 |
The schedule becomes empty after the third video, so the fourth starts immediately at time 10. The fifth notification arrives while the fourth is playing, so it waits until time 12.
Example 2
Input:
3
5 2
5 4
5 1
| Notification | Arrival | Duration | Previous finish | Start | New finish |
|---|---|---|---|---|---|
| 1 | 5 | 2 | 0 | 5 | 7 |
| 2 | 5 | 4 | 7 | 7 | 11 |
| 3 | 5 | 1 | 11 | 11 | 12 |
Every notification arrives together, but they are still processed in input order. The running finish time naturally preserves that ordering.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Every notification is processed exactly once. |
| Space | O(1) | Only the current finish time is stored. |
Processing 200000 notifications with constant work per notification easily fits within the time limit, and the constant memory usage is far below the available memory.
Test Cases
import sys
import io
def solve():
input = sys.stdin.readline
n = int(input())
finish = 0
for _ in range(n):
t, d = map(int, input().split())
finish = max(finish, t) + d
print(finish)
def run(inp: str) -> str:
backup_stdin = sys.stdin
backup_stdout = sys.stdout
sys.stdin = io.StringIO(inp)
out = io.StringIO()
sys.stdout = out
solve()
sys.stdin = backup_stdin
sys.stdout = backup_stdout
return out.getvalue().strip()
assert run("5\n1 4\n3 3\n6 1\n10 2\n10 3\n") == "15", "sample 1"
assert run("1\n7 5\n") == "12", "single notification"
assert run("2\n1 2\n10 3\n") == "13", "idle period"
assert run("3\n5 2\n5 4\n5 1\n") == "12", "same arrival time"
assert run("2\n1 4\n5 3\n") == "8", "arrival at finish"
assert run("3\n1 1000000000\n1 1000000000\n1 1000000000\n") == "3000000001", "large values"
| Test input | Expected output | What it validates |
|---|---|---|
| One notification | 12 | Minimum valid input |
| Idle gap | 13 | Schedule restarts after becoming idle |
| Equal arrival times | 12 | Input order is preserved |
| Arrival at finish | 8 | Boundary where a video ends exactly at notification time |
| Large durations | 3000000001 | Correct handling of very large finish times |
Edge Cases
Consider an idle gap:
2
1 2
10 3
The algorithm starts with finish = 0. After the first notification, finish = max(0, 1) + 2 = 3. For the second notification, finish = max(3, 10) + 3 = 13. The schedule correctly restarts at time 10 instead of continuing from time 3.
Now consider multiple notifications with the same timestamp.
3
5 2
5 4
5 1
The updates are 7, then 11, then 12. Every notification is processed in input order because each new start time depends on the finish time produced by earlier notifications.
Finally, consider a notification arriving exactly when the previous video ends.
2
1 4
5 3
After the first notification, finish = 5. The second update becomes max(5, 5) + 3 = 8. Since finish and the arrival time are equal, the new video begins immediately without any unnecessary waiting, matching the required behavior.