Клубный марафон

тема: Интервалы: покрытие и расписание · уровень: средний

Условие

В школе устроили «клубный марафон»: в течение дня проходят разные занятия (кружки, встречи, тренировки). Ты хочешь успеть на как можно больше занятий целиком.

Каждое занятие задано двумя числами s и t — оно начинается в момент s и заканчивается в момент t. Считай, что занятие занимает полуинтервал [s, t): если одно занятие заканчивается ровно в момент t, то на другое, начинающееся в момент t, ты успеваешь.

Нужно узнать, сколько занятий максимум можно посетить, если посещать их по очереди и не пересекаться по времени.

Формат ввода

Первая строка: целое число n — количество занятий. Далее n строк: по два целых числа s и t.

Формат вывода

Выведите одно целое число — максимальное количество занятий, которые можно посетить.

Ограничения

Пример

Ввод:

5
1 3
3 5
0 6
5 7
8 9

Вывод:

4

Пояснение: можно выбрать занятия [1,3), [3,5), [5,7), [8,9).

Как решать — идея подхода

Приём: Жадный выбор по раннему окончанию

Ключевое наблюдение: чтобы успеть на максимум занятий, выгодно как можно раньше «освобождать время» для следующих. Поэтому среди всех занятий, которые можно взять сейчас, лучший кандидат — тот, у которого конец минимальный.

Почему жадность работает: если вы в какой-то момент выбираете занятие, которое заканчивается позже, вы не расширяете возможности, а только сужаете их (раньше освобождённое время никогда не мешает). Значит, всегда можно заменить любой выбор на занятие с более ранним окончанием и не ухудшить ответ.

План решения:

Сложность: сортировка O(n log n), проход O(n). При n до 8000 работает мгновенно.

Частая ошибка: перепутать условие непересечения для полуинтервалов [s, t). Здесь занятие, начинающееся ровно в last_end, разрешено, поэтому нужно s >= last_end, а не s > last_end.

Разберись руками

Есть 5 занятий: [1,3), [3,5), [0,6), [5,7), [8,9). Ты можешь ходить только на непересекающиеся по времени, причём если одно заканчивается в момент t, то на другое с началом t ты успеваешь.

Идея: Если ты хочешь уместить максимум непересекающихся занятий, выгодно каждый раз выбирать из доступных то, которое заканчивается раньше всех: так ты быстрее «освобождаешь время» для следующих. Дальше просто идёшь по занятиям, и берёшь очередное, только если оно начинается не раньше, чем закончился последний выбранный.

Решить задачу с автопроверкой на Python →

Куда дальше