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.
#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);
}
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);
}
}
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)
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);
}
}
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