CSES Solutions - Movie Festival II

Last Updated : 23 Mar, 2026

In a movie festival, N movies will be shown. Syrjälä's movie club consists of K members, who will all be attending the festival. Given the starting and ending times of each movie. What is the maximum total number of movies the club members can watch entirely if they act optimally?

Examples:

Input: N = 5, K = 2, movies = {{1, 5}, {8, 10}, {3, 6}, {2, 5}, {6, 9}}
Output: 4
Explanation: The first member can watch 1st movie whose start time is 1 and end time is 5, and 5th movie whose start time is 6 and end time is 9. The second member can watch the movie 4th movie with a start time 2 and end time 4, and 2nd movie with start time 8 and end time 10. In this way total number of movies club members will watch entirely will be 4.

Input: N = 5, K = 1, movies = {{1, 5}, {8, 10}, {3, 6}, {2, 5}, {6, 9}}
Output: 2
Explanation: The first member can watch 1st movie whose start time is 1 and end time is 5 and 5th movie whose start time is 6 and end time is 9.

Greedy Scheduling with Multiset - O(n logk) Time and O(k) Space

  • Sort movies based on start time.
  • Assign the first k movies and store their end times in a multiset.
  • For each remaining movie, if start ≥ minimum end time, reuse that viewer and update the set.
  • Otherwise, if end < maximum end time, replace the worst movie in the set.
  • Maintain count of successfully reassigned movies during iteration.
  • Final answer = assigned count + size of multiset.
C++
#include <iostream>
using namespace std;

typedef long long ll;
bool sortcol2(const vector<ll> &v1, const vector<ll> &v2)
{
    return v1[0] < v2[0];
}

void MovieFestivalII(int n, int k, vector<vector<ll>> &a)
{
    // Multiset to store end times of assigned movies
    multiset<int> st;

    // Variable to keep track of entirely watchable movies
    ll ans = 0;

    // Initialize multiset with end times of first k movies
    for (int i = 0; i < k; i++)
    {
        st.insert(a[i][1]);
    }

    // Iterate over the remaining movies
    for (int i = k; i < n; i++)
    {
        // Iterator pointing to minimum end time
        auto mn = st.begin();
        // Iterator pointing to maximum end time
        auto mx = st.rbegin(); 

        // If the start time of the current movie is after or equal to the minimum end time,
        // it can be entirely watched, so increment the count and update the multiset
        if (a[i][0] >= (*mn))
        {
            ans++;
            st.erase(mn);
            st.insert(a[i][1]);
        }
        // If the end time of the current movie is less than the maximum end time,
        // replace the movie with the maximum end time in the multiset
        else if (a[i][1] < (*mx))
        {
            st.erase(st.find(*mx));
            st.insert(a[i][1]);
        }
    }

    // Print the total number of entirely watchable movies
    cout << ans + st.size() << "\n";
}

int main()
{
    int n=5, k=2;

    // Vector to store movie start and end times
    vector<vector<ll>> a={{1,5},{8,10},{3,6},{2,5},{6,9}};

    // Sort movies based on start times
    sort(a.begin(), a.end(), sortcol2);

    // Call the function to optimize movie-watching schedule
    MovieFestivalII(n, k, a);
}
Java
import java.util.*;

public class GfG {

    static class MovieComparator
        implements Comparator<long[]> {
        public int compare(long[] v1, long[] v2)
        {
            return Long.compare(v1[0], v2[0]);
        }
    }

    // Function to optimize movie-watching schedule
    static void movieFestivalII(int n, int k,
                                List<long[]> a)
    {
        // PriorityQueue to store end times of assigned
        // movies
        PriorityQueue<Long> pq = new PriorityQueue<>();

        // Variable to keep track of entirely watchable
        // movies
        long ans = 0;

        // Iterate over the movies
        for (int i = 0; i < n; i++) {
            long startTime = a.get(i)[0];
            long endTime = a.get(i)[1];

            // Remove movies that end before the current
            // movie's start time
            while (!pq.isEmpty()
                   && pq.peek() < startTime - 1) {
                pq.poll();
            }

            // If there are fewer than k movies currently
            // playing, add the current movie
            if (pq.size() < k) {
                pq.add(endTime);
                ans++;
            }
            else {
                // If the earliest ending movie finishes
                // before the current movie starts, replace
                // it
                if (!pq.isEmpty()
                    && pq.peek() < startTime) {
                    pq.poll();
                    pq.add(endTime);
                    ans++;
                }
            }
        }

        // Print the total number of entirely watchable
        // movies
        System.out.println(ans);
    }

    public static void main(String[] args)
    {
        int n = 5, k = 2;

        // List to store movie start and end times
        List<long[]> a = Arrays.asList(
            new long[] { 1, 5 }, new long[] { 8, 10 },
            new long[] { 3, 6 }, new long[] { 2, 5 },
            new long[] { 6, 9 });

        // Sort movies based on start times
        a.sort(new MovieComparator());

        // Call the function to optimize movie-watching
        // schedule
        GfG(n, k, a);
    }
}
Python
import heapq

def movie_festival_ii(n, k, a):

    # Sort by start time (same logic as your C++)
    a.sort(key=lambda x: x[0])

    pq = []  # min heap
    ans = 0

    # Initialize first k movies
    for i in range(min(k, n)):
        heapq.heappush(pq, a[i][1])

    # Process remaining movies
    for i in range(k, n):

        start, end = a[i]

        # Smallest end time
        mn = pq[0]

        # If current movie can fit
        if start >= mn:
            ans += 1

            heapq.heappop(pq)
            heapq.heappush(pq, end)

        else:
            # To replace largest, we simulate using max check
            # Convert heap to get max (costly but happens rarely)
            mx = max(pq)

            if end < mx:
                pq.remove(mx)      # remove largest
                heapq.heapify(pq)  # restore heap
                heapq.heappush(pq, end)

    print(ans + len(pq))

n = 5
k = 2

a = [[1, 5], [8, 10], [3, 6], [2, 5], [6, 9]]

movie_festival_ii(n, k, a)
C#
using System;
using System.Collections.Generic;
using System.Linq;

public class GfG
{
    public static void MovieFestivalII(int n, int k, List<List<long>> a)
    {
        // Sorted dictionary to store end times of assigned movies
        SortedDictionary<long, int> st = new SortedDictionary<long, int>();

        // Variable to keep track of entirely watchable movies
        long ans = 0;

        // Initialize dictionary with end times of first k movies
        for (int i = 0; i < k; i++)
        {
            if (!st.ContainsKey(a[i][1]))
                st.Add(a[i][1], 0);
            st[a[i][1]]++;
        }

        // Iterate over the remaining movies
        for (int i = k; i < n; i++)
        {
            // Get the minimum end time
            var min = st.First().Key;
            // Get the maximum end time
            var max = st.Last().Key;

            // If the start time of the current movie is after or equal to the minimum end time,
            // it can be entirely watched, so increment the count and update the dictionary
            if (a[i][0] >= min)
            {
                ans++;
                if (st.ContainsKey(min))
                {
                    if (st[min] == 1)
                        st.Remove(min);
                    else
                        st[min]--;
                }
                if (!st.ContainsKey(a[i][1]))
                    st.Add(a[i][1], 0);
                st[a[i][1]]++;
            }
            // If the end time of the current movie is less than the maximum end time,
            // replace the movie with the maximum end time in the dictionary
            else if (a[i][1] < max)
            {
                if (st.ContainsKey(max))
                {
                    if (st[max] == 1)
                        st.Remove(max);
                    else
                        st[max]--;
                }
                if (!st.ContainsKey(a[i][1]))
                    st.Add(a[i][1], 0);
                st[a[i][1]]++;
            }
        }

        // Print the total number of entirely watchable movies
        Console.WriteLine(ans + st.Count);
    }
    
    public static void Main(string[] args)
    {
        int n = 5, k = 2;

        // List to store movie start and end times
        List<List<long>> a = new List<List<long>>()
        {
            new List<long>() {1, 5},
            new List<long>() {8, 10},
            new List<long>() {3, 6},
            new List<long>() {2, 5},
            new List<long>() {6, 9}
        };

        // Sort movies based on start times
        a.Sort((x, y) => x[0].CompareTo(y[0]));

        // Call the function to optimize movie-watching schedule
        GfG(n, k, a);
    }
}
JavaScript
function movie_festival_ii(n, k, a) {
    // Sorting function to sort movies based on start times
    function movie_comparator(v1, v2) {
        return v1[0] - v2[0];
    }

    // PriorityQueue to store end times of assigned movies
    let pq = [];

    // Variable to keep track of entirely watchable movies
    let ans = 0;

    // Iterate over the movies
    for (let i = 0; i < n; i++) {
        let startTime = a[i][0];
        let endTime = a[i][1];

        // Remove movies that end before the current movie's start time
        while (pq.length > 0 && pq[0] < startTime - 1) {
            pq.shift();
        }

        // If there are fewer than k movies currently playing, add the current movie
        if (pq.length < k) {
            pq.push(endTime);
            ans += 1;
        } else {
            // If the earliest ending movie finishes before the current movie starts, replace it
            if (pq.length > 0 && pq[0] < startTime) {
                pq.shift();
                pq.push(endTime);
                ans += 1;
            }
        }
    }

    // Print the total number of entirely watchable movies
    console.log(ans);
}

// driver code
let n = 5;
let k = 2;

// List to store movie start and end times
let a = [[1, 5], [8, 10], [3, 6], [2, 5], [6, 9]];

// Sort movies based on start times
a.sort((x, y) => x[0] - y[0]);

// Call the function to optimize movie-watching schedule
movie_festival_ii(n, k, a);

Output
4
Comment