DSA sheet / Sorting and searching

Movie Festival

medium about 20 min greedysorting
Open on CSES

Do these first: Restaurant Customers

The problem in brief

There are n movies (up to 200 000), each with a start and end time. You watch each chosen movie in full and cannot watch two at once. Print the maximum number of movies you can watch.

Try it

Tab indents; press Esc, then Tab, to leave the box. Ctrl+Enter runs.

Hints

Stuck? Reveal one hint at a time. Each nudges without giving away the next.

The walkthrough

Spoilers ahead: open a section only after you have given the hints a fair try.

How to think

Interval scheduling is the textbook example of a greedy algorithm proven by an exchange argument. Brute force over subsets is exponential, and a DP over time is impossible with times up to 10^9, so a greedy is the only realistic route. The skill is choosing the right greedy criterion.

“Earliest start” fails (a very long movie starting first blocks everything). “Shortest” fails (a short movie in the middle can block two others). “Earliest finish” works: among all movies you could watch first, the one that ends soonest leaves the maximum remaining time, and any solution that starts with a different movie can swap its first movie for this one without losing anything, because the earliest-ending movie finishes no later.

The habit: when unsure which greedy criterion is right, look for counterexamples to the tempting ones and then prove the survivor by the exchange argument.

Intuition

At every step, pick whichever movie lets you get out of the cinema soonest. Then you are back to the same problem with a shorter timeline. Repeating that never paints you into a corner.

Approach
  1. Sort the movies by end time.
  2. Keep lastEnd (initially 0 or minus infinity). For each movie in that order: if its start is at least lastEnd, watch it: count it and set lastEnd to its end.
  3. Print the count.

Tie rule: a movie that starts exactly when the previous one ends is allowed (start >= lastEnd). Pitfalls: sort by end time, not start; movies with the same end are interchangeable for this algorithm; times up to 10^9 fit in 32-bit ints.

Complexity

O(n log n) time for the sort, O(n) for the sweep; O(n) memory.

Solutions

Written from scratch and checked by compiling and running each one against a brute force on random inputs. Fast input/output, the way you would submit it.

Show solutions (C++17, Python 3, Java 17, Node.js)
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<pair<int, int>> mv(n);  // (end, start): sorting orders by end time
    for (auto &m : mv) cin >> m.second >> m.first;
    sort(mv.begin(), mv.end());
    int count = 0, lastEnd = 0;
    for (auto &m : mv) {
        if (m.second >= lastEnd) {
            count++;
            lastEnd = m.first;
        }
    }
    cout << count << "\n";
    return 0;
}

Problem: CSES Problem Set (Antti Laaksonen, University of Helsinki), CC BY-NC-SA 4.0. The explanations and code above are original (© Anupam Kumar).

Related problems

Back to the sheet