Triathlon
Editorial written by Roumak Das.
Every citizen goes through three tracks in the same order: programming, then pole vault, then doughnut eating. Citizen needs , and time on them. There is only one computer, so at most one person can be programming at any moment, and we get to decide the queue. The other two tracks have room for everybody at once. We want the last person to finish as early as possible.
Where the time actually goes
Let’s fix an order and follow whoever is -th in the queue. They cannot touch the computer until everyone ahead of them is finished with it, so they start at and hold it for . After that nothing delays them, since the last two tracks have no capacity limit, so they finish at
The event ends when the slowest of them is done, so the answer is the maximum of this over all .
Try to see what you can do with this formula. The solution is mostly hidden in it.
Hint 1
Look at how and appear. They never show up apart from each other, only ever as a sum. So a citizen is really just two numbers: the time they block the computer for, and they spend on their own afterwards.
Hint 2
Whatever order you choose, the prefix sums of are built from the same values, so the multiset of prefix totals never changes. Reordering does not change which prefixes exist. All it changes is which gets paired with which prefix.
So the real question is how to pair them.
Key idea
Someone with a long tail after the computer should get to it early, so their tail runs while everyone else is still queueing. Notice that plays no part in the rule at all.
Why the sorted order is optimal
As in the key idea above, write for the time citizen spends after leaving the computer.
Claim. If , then scheduling immediately before is never worse than the other way round.
Proof. Take any order, and pick two citizens and standing next to each other. Let be the total of everyone ahead of both of them, and let .
Swapping the two disturbs nobody else. People ahead are untouched, and people behind still get the computer at , since the pair occupies it for either way. So we only have to compare the two finish times inside the pair.
With first, the two finish at and . With first, they finish at and .
Assume , and compare everything against , which the second arrangement always pays:
- , because
- , because
Both finish times of the first arrangement are at most something the second arrangement pays anyway, so putting the bigger first is never worse.
This only talks about neighbours, but that is enough. If an order is not sorted by descending , then some adjacent pair in it is in the wrong relative order, and swapping that pair cannot increase the answer. Repeat the swap until the order is fully sorted. Nothing got worse along the way, so the sorted order is optimal. Ties in can go either way.
Implementation
Sort with the rule above, then walk through once carrying a running prefix sum.
#include <bits/stdc++.h>
using namespace std;
bool compare(const vector<long long> &p, const vector<long long> &q) {
return p[1] + p[2] > q[1] + q[2];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<long long>> v(n, vector<long long>(3));
for (int i = 0; i < n; i++) {
cin >> v[i][0] >> v[i][1] >> v[i][2];
}
sort(v.begin(), v.end(), compare);
long long prefix = 0;
long long ans = 0;
for (int i = 0; i < n; i++) {
prefix += v[i][0];
long long finish = prefix + v[i][1] + v[i][2];
if (finish > ans) {
ans = finish;
}
}
cout << ans << '\n';
}int,
but with under 7% of room left before INT_MAX. Using 64-bit costs nothing and saves you from
redoing that bound during a contest.Time complexity: for the sort and for the sweep. Memory is . This fits well inside the 2 second and 32 MB limits, and the same code clears both subtasks.
Worked example
The sample gives for citizens , so sorting by descending puts them in the order :
| Position | Citizen | prefix | finish | ||
|---|---|---|---|---|---|
| 1 | 2 | 23 | 23 | 37 | 60 |
| 2 | 3 | 20 | 43 | 23 | 66 |
| 3 | 1 | 18 | 61 | 13 | 74 |
The event ends at , which matches the expected output.