CSES Solutions Movie Festival II (original) (raw)

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

#include using namespace std;

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

void MovieFestivalII(int n, int k, vector<vector> &a) { // Multiset to store end times of assigned movies multiset 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> 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);

`