Medium · greedy

Minimum Waiting Time

Whoever goes first makes nobody wait; whoever goes last makes everybody wait. Every minute of a person's fill time is paid by everyone behind them — so the cheapest queue puts small times where they multiply least.

At a glanceSort ascending, then accumulate: person i waits the sum of everyone before them. <code>total += wait; wait += a[i]</code> after sorting is the whole solution.

Problem

Input: The first line is n (1 ≤ n ≤ 100). The second line has n integers (1 ≤ a ≤ 1000): each person's fill time in seconds.

Output: The minimum possible total waiting time, where a person's waiting time is everything before their own fill starts (their own fill does not count).

Samples:

InputOutput
4
3 1 4 1
8
1
5
0

For the sample, the best order is 1, 1, 3, 4: waits are 0, 1, 2, 5 — total 8. Any other order pays more; the sorted order is provably the minimum.

Your solution

main.cpp — your solution
Custom input for "Run my input"

Judging runs in your browser against hidden tests. A runaway loop is cut off after 3 seconds — still, make sure every loop has an exit. Your code is saved in this browser as you type.

Stuck? Hints

Hint 1 — Write what a swap changes

Take two neighbours x before y and imagine swapping them. Only those two waiting times change: with x first they pay y, with y first they pay x. Swapping is better exactly when y < x — so in an optimal queue every neighbour pair is ascending, which forces the whole queue to be sorted. That is the exchange argument, and it is how you prove a greedy instead of hoping.

Hint 2 — The sweep is a running prefix

After sorting, person i waits for the sum of a[0..i-1]. Instead of an inner loop, carry wait: for each person in order, total += wait; then wait += a[i];. Two additions per person, no second loop — the same prefix idea as Range Sum Queries.

Hint 3 — Waiting starts before, not after

The statement says a person's own fill time does not count as waiting. The running-prefix sweep gets this right for free — but if you instead compute prefix sums including a[i], every answer comes out too large by Σa[i], and the bug hides inside a plausible-looking number.

Solution (try it first!)
#include <iostream>
using namespace std;

int a[105];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];

    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (a[j] > a[j + 1]) {
                int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t;
            }
        }
    }

    long long total = 0, wait = 0;
    for (int i = 0; i < n; i++) {
        total += wait;
        wait += a[i];
    }
    cout << total << endl;
    return 0;
}

This is the shortest-job-first principle from operating systems, proved with four lines of exchange argument. Its sibling you already met: Minimum Coins was greedy with a different proof, and Bubble Sort is the machinery both reuse. When a greedy feels right, the exercise is always the same: find the swap that would improve any non-sorted answer.

Deep dive

Why this works

Exchange argument: take any queue that is not sorted ascending and swap an adjacent out-of-order pair (x before y with y < x). Only those two people's waits change, and they drop by x − y. So an unsorted queue can always be improved, and the unique local optimum is the sorted one — that is a proof, not a hope.

The cost

O(n²) for the bubble sort and O(n) for the sweep; with n ≤ 100 that is about 10,000 comparisons. Total wait fits easily in 64 bits (100 people × 1000 s ≈ 5 million seconds of waiting).

Where it goes wrong

  • Counting each person's own fill time as waiting inflates every answer by Σa[i] — the sweep must add wait BEFORE extending it with a[i].
  • Sorting the display copy but sweeping the original array (or vice versa) — the answer silently corresponds to neither order.
  • Forgetting that equal times can sit in any order among themselves: ties are free, do not complicate the sort for them.

Next step

The greedy sibling with a different proof is Minimum Coins — read the two exchange arguments side by side. The sort both reuse is Bubble Sort.

Two things to remember

  • Fast first: every minute of the front person's time is paid by everyone behind.
  • Swap argument = the proof template for greedy: find the swap that improves any unsorted answer.
🐞 This version fails — open it and try

Sweeps in arrival order — the queue was never sorted

#include <iostream>
using namespace std;

int a[105];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];
    long long total = 0, wait = 0;
    for (int i = 0; i < n; i++) {   // bug: no sorting first
        total += wait;
        wait += a[i];
    }
    cout << total << endl;
    return 0;
}