Подготовка к школе
1 класс
2 класс
3 класс
4 класс
5 класс
6 класс
7 класс
8 класс
9 класс
10 класс
11 класс
ОГЭ
ЕГЭ
Для всех
Назад

26. Прикладная задача: все задания

Сообщить о проблеме
1. Задание #297682
Задание было решено верно
Задание было решено неверно

Организация купила для своих сотрудников все места в нескольких подряд идущих рядах на концертной площадке. Известно, какие места уже распределены между сотрудниками. Найдите ряд с наибольшим номером, в котором есть два соседних места, таких что слева и справа от них в том же ряду места уже распределены (заняты). Гарантируется, что есть хотя бы один ряд, удовлетворяющий этому условию. В ответе запишите два целых числа без пробелов: номер ряда и наименьший номер места из найденных в этом ряду подходящих пар свободных мест.

Входные данные

В первой строке входного файла находится число $N$ – количество занятых мест (натуральное число, не превышающее $10000$). Каждая из следующих $N$ строк содержит два натуральных числа, не превышающих $100000$: номер ряда и номер занятого места.

Выходные данные

Два целых неотрицательных числа: номер ряда и наименьший номер места в выбранной паре.

Пример входного файла:

7
40 3
40 6
60 33
50 125
50 128
50 64
50 67

Условию задачи удовлетворяют три пары чисел: $40$ и $4$, $50$ и $126$, $50$ и $65$. Ответ для приведённого примера: $50$ $65$.

Место свободно, если его нет в списке занятых. Нужна пара соседних свободных мест, окружённая занятыми — то есть занятые места $a$ и $b$ в одном ряду, между которыми ровно два свободных. Это в точности условие $b — a = 3$.

Значит группируем занятые места по рядам, каждый ряд сортируем и смотрим только на соседние элементы отсортированного списка: если разница равна $3$, найдена подходящая пара, её меньший номер равен $a+1$. Перебирать все места ряда не нужно — их номера доходят до $100000$, а занятых всего $10000$.

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

from collections import defaultdict

f = open('26-01.txt')
n = int(f.readline())

rows = defaultdict(list)
for _ in range(n):
    r, p = map(int, f.readline().split())
    rows[r].append(p)

best_row, best_seat = -1, None
for r, seats in rows.items():
    seats = sorted(set(seats))
    # разница 3 между занятыми = ровно два свободных места между ними
    pairs = [seats[i] + 1 for i in range(len(seats) - 1) if seats[i+1] - seats[i] == 3]
    if pairs and r > best_row:
        best_row, best_seat = r, min(pairs)

print(best_row, best_seat)   # 69969 58998

Проверка. Подходящих рядов в файле $994$ штуки, максимальный по номеру из них — $69969$. В нём занято $11$ мест и нашлось три подходящих пары, начинающихся с мест $58998$, $80983$ и $93106$; наименьшая из них и идёт в ответ.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
2. Задание #297683
Задание было решено верно
Задание было решено неверно

Входной файл содержит сведения о заявках на проведение мероприятий в конференц-зале. В каждой заявке указаны время начала и время окончания мероприятия (в минутах от начала суток). Если время начала одного мероприятия меньше времени окончания другого, то провести можно только одно из них. Если время окончания одного мероприятия совпадает со временем начала другого, то провести можно оба. Определите, какое максимальное количество мероприятий можно провести в конференц-зале, и каков при этом максимально возможный перерыв между двумя последними мероприятиями.

Входные данные

В первой строке входного файла находится натуральное число $N$ ($N \le 1000$) – количество заявок на проведение мероприятий. Следующие $N$ строк содержат пары чисел, обозначающих время начала и время окончания мероприятий. Каждое из чисел натуральное, не превосходящее $1440$.

Запишите в ответе два числа: максимальное количество мероприятий и самый длинный перерыв между двумя последними мероприятиями (в минутах).

Типовой пример организации данных во входном файле:

5
10 150
100 120
131 170
150 180
120 130

При таких исходных данных можно провести максимум три мероприятия, например, мероприятия по заявкам $2$, $3$ и $5$. Максимальный перерыв между двумя последними мероприятиями составит $20$ мин., если состоятся мероприятия по заявкам $2$, $4$ и $5$.

Два мероприятия совместимы, если конец одного не позже начала другого. Первая часть — классическая задача о выборе заявок: сортируем мероприятия по времени окончания и жадно берём каждое, которое начинается не раньше конца предыдущего взятого. Это даёт максимум $25$.

Вторая часть сложнее, потому что расписаний с максимальным количеством мероприятий много, а перерыв нужен наибольший по всем таким расписаниям. Поэтому вместо жадности считаем динамику: для каждого мероприятия $i$ находим $cnt[i]$ — сколько мероприятий максимум умещается в цепочке, которая заканчивается именно этим. Максимум по всем $cnt$ и есть ответ на первый вопрос, обозначим его $K$.

Теперь пара последних мероприятий. Последнее — это любое $j$ с $cnt[j] = K$, а предыдущее — любое совместимое с ним $i$, у которого $cnt[i] = K-1$: тогда цепочка из $K-1$ мероприятий заканчивается на $i$, а $j$ добавляется двадцать пятым. Перерыв равен разности между началом $j$ и концом $i$, берём наибольший.

f = open('26-02.txt')
n = int(f.readline())
ev = [tuple(map(int, f.readline().split())) for _ in range(n)]
ev.sort(key=lambda x: x[1])                 # по времени окончания

cnt = [0] * n            # макс. число мероприятий в цепочке, кончающейся i-м
for i, (a, b) in enumerate(ev):
    best = 0
    for k in range(i):
        if ev[k][1] <= a and cnt[k] > best:  # конец не позже начала
            best = cnt[k]
    cnt[i] = best + 1

K = max(cnt)

gap = 0
for j, (a, b) in enumerate(ev):
    if cnt[j] != K:                          # j должно быть последним в цепочке
        continue
    for i in range(j):
        if cnt[i] == K - 1 and ev[i][1] <= a:
            gap = max(gap, a - ev[i][1])

print(K, gap)   # 25 16

Проверка. Простой подсчёт на том же файле тоже даёт $25$ мероприятий. На типовом примере из условия программа выдаёт $3$ и $20$, что совпадает с приведённым разбором.

Квадратичная динамика здесь вполне уместна: при $N \le 1000$ это порядка миллиона операций.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
3. Задание #297684
Задание было решено верно
Задание было решено неверно

При онлайн-покупке билета на концерт известно, какие места в зале уже заняты. Необходимо купить билет на такое место в ряду, чтобы перед ним как можно больше идущих подряд кресел с таким же номером было свободно. Если места, удовлетворяющие этому условию, есть в нескольких рядах, то нужно выбрать ряд, расположенный как можно ближе к сцене. В ответе запишите два целых числа: искомый номер ряда и количество свободных кресел перед выбранным местом. Нумерация рядов и мест ведётся с $1$. Гарантируется, что хотя бы одно такое место в зале есть.

Входные данные

В первой строке входного файла находятся три числа: $N$ – количество занятых мест в зале (целое положительное число, не превышающее $10000$), $M$ – количество рядов (целое положительное число, не превышающее $100000$) и $K$ – количество мест в каждом ряду (целое положительное число, не превышающее $100000$). В следующих $N$ строках находятся пары натуральных чисел: номер ряда и номер места занятого кресла соответственно (первое число не превышает значения $M$, а второе – $K$).

Выходные данные

Два целых положительных числа: искомый номер ряда и количество свободных кресел перед выбранным местом.

Типовой пример организации данных во входном файле:

9 6 7
1 1
2 4
3 6
6 1
4 3
5 5
5 2
6 6
4 7

При таких исходных данных условию задачи удовлетворяют места (ряд, место): $5$, $1$; $4$, $2$; $6$, $4$; $4$, $5$. Перед этими местами три подряд кресла свободны. Ответом является пара чисел $4$ и $3$.

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

Внутри одной линии интересны лишь занятые ряды. Отсортируем их. Между двумя соседними занятыми рядами лежит участок свободных, и выгоднее всего сесть в самом дальнем ряду этого участка: тогда перед нами окажется весь участок целиком. Если предыдущий занятый ряд имеет номер $prev$, а выбранное место стоит в ряду $r$, то свободных перед ним ровно $r — prev — 1$.

Так что для каждой линии достаточно пройтись по занятым рядам, для каждого взять ряд непосредственно перед ним, а в конце отдельно рассмотреть хвост до последнего ряда зала. Плюс отдельная ветка на случай, когда какой-то номер места не занят вообще нигде: тогда можно сесть в самый дальний ряд $M$, и перед нами будут свободны все $M-1$ рядов.

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

from collections import defaultdict

f = open('26-03.txt')
N, M, K = map(int, f.readline().split())

occ = defaultdict(list)                  # номер места -> список занятых рядов
for _ in range(N):
    r, p = map(int, f.readline().split())
    occ[p].append(r)

best, best_row = -1, None
def upd(cnt, row):
    global best, best_row
    if cnt > best or (cnt == best and row < best_row):
        best, best_row = cnt, row

if len(occ) < K:                         # есть место, свободное во всех рядах
    upd(M - 1, M)

for p, rows in occ.items():
    rows.sort()
    prev = 0
    for o in rows:
        r = o - 1                        # самый дальний свободный ряд перед занятым
        if r > prev:
            upd(r - prev - 1, r)
        prev = o
    if M > prev:                         # хвост до конца зала
        upd(M - prev - 1, M)

print(best_row, best)   # 68217 33508

Проверка. В файле $N = 9996$, $M = 99931$, $K = 3332$, причём занятые места покрывают все $3332$ номера, так что ветка с полностью свободной линией не сработала. Ответ даёт место номер $620$ в ряду $68217$: само оно свободно, и перед ним подряд свободны ровно $33508$ кресел с тем же номером. На типовом примере из условия программа выдаёт $4$ и $3$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
4. Задание #297690
Задание было решено верно
Задание было решено неверно

На грузовом судне необходимо перевезти контейнеры, имеющие одинаковый габарит и разные массы. Общая масса всех контейнеров превышает грузоподъёмность судна. Количество грузовых мест на судне не меньше количества контейнеров, назначенных к перевозке. Какое максимальное количество контейнеров можно перевезти за один рейс и какова масса самого тяжёлого контейнера среди всех контейнеров, которые можно перевезти за один рейс?

Входные данные

В первой строке входного файла находятся два числа: $S$ – грузоподъёмность судна (натуральное число, не превышающее $100000$) и $N$ – количество контейнеров (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения масс контейнеров, требующих транспортировки (все числа натуральные, не превышающие $100$), каждое в отдельной строке.

Выходные данные

Два целых неотрицательных числа: максимальное количество контейнеров, которые можно перевезти за один рейс, и масса наиболее тяжёлого из них.

Пример входного файла:

100 4
80
30
50
40

При таких исходных данных можно транспортировать за один раз максимум $2$ контейнера. Возможные массы этих двух контейнеров $30$ и $40$, $30$ и $50$ или $40$ и $50$. Поэтому ответ для приведённого примера: $2$ $50$.

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

Вторая часть требует аккуратности. Спрашивается не про самый тяжёлый контейнер конкретного набора, а про максимально возможный среди всех наборов размера $k$. Чтобы освободить как можно больше места под один тяжёлый контейнер, остальные $k-1$ надо взять самыми лёгкими. Считаем их суммарную массу, вычитаем из грузоподъёмности и ищем среди оставшихся контейнеров самый тяжёлый, который в этот остаток укладывается.

f = open('26-04.txt')
S, N = map(int, f.readline().split())
w = sorted(int(f.readline()) for _ in range(N))

total, k = 0, 0
for x in w:                              # набираем самые лёгкие
    if total + x > S:
        break
    total += x
    k += 1

base = sum(w[:k-1])                      # k-1 самых лёгких берём обязательно
heaviest = max(x for x in w[k-1:] if base + x <= S)

print(k, heaviest)   # 1612 90

Проверка. Грузоподъёмность $99990$, контейнеров $9999$ общей массой $749769$, массы лежат в диапазоне от $60$ до $90$. Максимум помещается $1612$ контейнеров. Масса $1611$ самых лёгких равна $99867$, свободного места остаётся $123$, и самый тяжёлый контейнер в файле массой $90$ туда свободно входит: $99867 + 90 = 99957 \le 99990$. На типовом примере из условия программа выдаёт $2$ и $50$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
5. Задание #297689
Задание было решено верно
Задание было решено неверно

Входной файл содержит сведения о заявках на проведение мероприятий в конференц-зале. В каждой заявке указаны время начала и время окончания мероприятия (в минутах от начала суток). Если время начала одного мероприятия меньше времени окончания другого, то провести можно только одно из них. Если время окончания одного мероприятия совпадает со временем начала другого, то провести можно оба. Определите максимальное количество мероприятий, которые можно провести в конференц-зале, и самое позднее время окончания последнего мероприятия в этом случае.

Входные данные

В первой строке входного файла находится натуральное число $N$ ($N \le 1000$) – количество заявок на проведение мероприятий. Следующие $N$ строк содержат пары чисел, обозначающих время начала и время окончания мероприятий (в минутах от начала суток). Каждое из чисел натуральное, не превосходящее $1440$.

Запишите в ответе два числа: максимальное количество мероприятий и самое позднее время окончания последнего мероприятия (в минутах от начала суток).

Типовой пример организации данных во входном файле:

5
10 150
100 110
131 170
131 180
120 130

При таких исходных данных можно провести максимум три мероприятия, например, по заявкам $2$, $3$ и $5$. Конференц-зал освободится самое позднее на $180$-й минуте, если состоятся мероприятия по заявкам $2$, $4$ и $5$.

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

Но второй вопрос жадность не решает. Расписаний с максимальным количеством мероприятий много, и то, которое построила жадность, заканчивается раньше других: она специально выбирает самые ранние концы. Здесь же нужно самое позднее окончание среди всех оптимальных расписаний.

Поэтому считаем динамику: для каждого мероприятия $i$ находим $cnt[i]$ — сколько мероприятий максимум умещается в цепочке, которая заканчивается именно этим. Максимум по всем $cnt$ даёт ответ на первый вопрос, обозначим его $K$. Затем среди всех мероприятий с $cnt[i] = K$ берём наибольшее время окончания: каждое такое мероприятие может быть последним в некотором оптимальном расписании.

f = open('26-05.txt')
n = int(f.readline())
ev = [tuple(map(int, f.readline().split())) for _ in range(n)]
ev.sort(key=lambda x: x[1])                  # по времени окончания

cnt = [0] * n            # макс. число мероприятий в цепочке, кончающейся i-м
for i, (a, b) in enumerate(ev):
    best = 0
    for k in range(i):
        if ev[k][1] <= a and cnt[k] > best:   # конец не позже начала
            best = cnt[k]
    cnt[i] = best + 1

K = max(cnt)
last = max(b for (a, b), c in zip(ev, cnt) if c == K)

print(K, last)   # 53 1300

Проверка. Жадный подсчёт на том же файле тоже даёт $53$ мероприятия, но его расписание освобождает зал уже на $1057$-й минуте — на четверть суток раньше найденного оптимума. При этом $1300$ меньше, чем самое позднее окончание в файле вообще ($1399$): то мероприятие в цепочку из $53$ штук не встраивается. На типовом примере из условия программа выдаёт $3$ и $180$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
6. Задание #297694
Задание было решено верно
Задание было решено неверно

В магазине для упаковки подарков есть $N$ кубических коробок. Самой интересной считается упаковка подарка по принципу матрёшки – подарок упаковывается в одну из коробок, та в свою очередь в другую коробку и т.д. Одну коробку можно поместить в другую, если длина её стороны хотя бы на $3$ единицы меньше длины стороны другой коробки. Определите наибольшее количество коробок, которое можно использовать для упаковки одного подарка, и максимально возможную длину стороны самой маленькой коробки, где будет находиться подарок. Размер подарка позволяет поместить его в самую маленькую коробку.

Входные данные

В первой строке входного файла находится число $N$ – количество коробок в магазине (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения длин сторон коробок (все числа натуральные, не превышающие $10000$), каждое – в отдельной строке.

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

Типовой пример организации данных во входном файле:

5
43
40
32
40
30

Пример входного файла приведён для пяти коробок и случая, когда минимальная допустимая разница между длинами сторон коробок, подходящих для упаковки «матрёшкой», составляет $3$ единицы. При таких исходных данных условию задачи удовлетворяют наборы коробок с длинами сторон $30$, $40$ и $43$ или $32$, $40$ и $43$ соответственно, т.е. количество коробок равно $3$, а длина стороны самой маленькой коробки равна $32$.

Отсортируем длины сторон по возрастанию. Матрёшка — это цепочка, в которой каждая следующая коробка больше предыдущей хотя бы на $3$. Максимальную длину даёт обычная жадность: идём по возрастанию и берём коробку, если она подходит к последней взятой.

Со вторым вопросом жадность не справляется: она начинает с самой маленькой коробки, а нам нужна самая большая из возможных стартовых. Поэтому считаем для каждой коробки $ln[i]$ — длину максимальной цепочки, которая начинается именно с неё.

Тут есть удобное свойство: чем меньше коробка, тем длиннее цепочка от неё, потому что любую цепочку, начинающуюся с большей коробки, можно начать и с меньшей. Значит $ln$ не возрастает по мере роста стороны, и максимум среди подходящих продолжений достигается на самой первой коробке со стороной не менее $a_i + 3$. Её и находим двоичным поиском, а массив заполняем справа налево.

Затем берём $K$ — наибольшее значение в $ln$, и среди всех коробок с таким значением выбираем самую большую сторону.

from bisect import bisect_left

f = open('26-06.txt')
n = int(f.readline())
a = sorted(int(f.readline()) for _ in range(n))

ln = [1] * n                       # длина макс. цепочки, начинающейся с i-й коробки
for i in range(n-1, -1, -1):
    j = bisect_left(a, a[i] + 3)   # первая коробка, в которую влезет i-я
    if j < n:
        ln[i] = 1 + ln[j]

K = max(ln)
smallest = max(a[i] for i in range(n) if ln[i] == K)

print(K, smallest)   # 2767 51

Проверка. В файле $10000$ коробок со сторонами от $50$ до $9998$, жадный подсчёт тоже даёт цепочку из $2767$ коробок. Цепочка, стартующая с коробки $51$, действительно содержит $2767$ штук, а если бы мы начали со следующей по размеру коробки $52$, вышло бы уже только $2766$. На типовом примере из условия программа выдаёт $3$ и $32$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
7. Задание #297692
Задание было решено верно
Задание было решено неверно

Входной файл содержит заявки пассажиров, желающих сдать свой багаж в камеру хранения. В заявке указаны время сдачи багажа и время освобождения ячейки (в минутах от начала суток). Багаж одного пассажира размещается в одной свободной ячейке с минимальным номером. Ячейки пронумерованы начиная с единицы. Размещение багажа в ячейке или её освобождение происходит в течение $1$ мин. Багаж можно поместить в только что освобождённую ячейку начиная со следующей минуты. Если в момент сдачи багажа свободных ячеек нет, то пассажир уходит. Определите, сколько пассажиров сможет сдать свой багаж в течение $24$ ч и какой номер будет иметь ячейка, которую займут последней. Если таких ячеек несколько, укажите минимальный номер ячейки.

Входные данные

В первой строке входного файла находится натуральное число $K$, не превышающее $1000$, – количество ячеек в камере хранения. Во второй строке – натуральное число $N$ ($N \le 1000$), обозначающее количество пассажиров. Каждая из следующих $N$ строк содержит два натуральных числа, каждое из которых не превышает $1440$: указанное в заявке время размещения багажа в ячейке и время освобождения ячейки (в минутах от начала суток).

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

Типовой пример организации данных во входном файле:

2
5
30 60
40 1000
59 60
61 1000
1010 1440

При таких исходных данных положить вещи в камеру хранения смогут первый, второй, четвёртый и пятый пассажиры. Последний пассажир положит вещи в ячейку $1$, так как ячейки $1$ и $2$ будут свободны.

Это прямое моделирование, никакой оптимизации искать не нужно. Заявки в файле лежат вперемешку, поэтому первым делом сортируем их по времени сдачи багажа — обслуживать пассажиров надо в порядке их прихода.

Для каждой ячейки храним одно число: момент, когда она освобождается. Пассажир с временем прихода $t$ может занять ячейку, если она освободилась строго раньше, то есть если записанное для неё время меньше $t$. Это ровно та формулировка «начиная со следующей минуты» из условия: ячейка, освобождённая в минуту $60$, доступна с минуты $61$.

Перебираем ячейки по возрастанию номера и берём первую подходящую — так выполняется требование про минимальный номер. Если подходящей нет, пассажир уходит. Попутно считаем успешных пассажиров и запоминаем, кто занял ячейку последним по времени; при совпадении времени берём меньший номер ячейки.

f = open('26-07.txt')
K = int(f.readline())
N = int(f.readline())
req = [tuple(map(int, f.readline().split())) for _ in range(N)]
req.sort()                                # по времени сдачи багажа

free = [0] * K                            # время, когда ячейка освободится
cnt = 0
last_t, last_cell = -1, None

for t, e in req:
    for i in range(K):
        if free[i] < t:                   # доступна со следующей минуты
            free[i] = e
            cnt += 1
            if t > last_t:
                last_t, last_cell = t, i + 1
            elif t == last_t and i + 1 < last_cell:
                last_cell = i + 1
            break

print(cnt, last_cell)   # 368 83

Проверка. Ячеек $210$, заявок $987$, успешными оказались $368$ пассажиров. Последняя сдача багажа среди них произошла на $997$-й минуте, и в этот момент был всего один такой пассажир — он занял ячейку $83$. На типовом примере из условия программа выдаёт $4$ и $1$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
8. Задание #297693
Задание было решено верно
Задание было решено неверно

В магазине для упаковки подарков есть $N$ кубических коробок. Самой интересной считается упаковка подарка по принципу матрёшки – подарок упаковывается в одну из коробок, та в свою очередь в другую коробку и т.д. Одну коробку можно поместить в другую, если длина её стороны хотя бы на $10$ единиц меньше длины стороны другой коробки. Определите наибольшее количество коробок, которое можно использовать для упаковки одного подарка, и максимально возможную длину стороны самой маленькой коробки, где будет находиться подарок. Размер подарка позволяет поместить его в самую маленькую коробку.

Входные данные

В первой строке входного файла находится число $N$ – количество коробок в магазине (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения длин сторон коробок (все числа натуральные, не превышающие $10000$), каждое – в отдельной строке.

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

Типовой пример организации данных во входном файле:

5
43
40
32
40
30

Пример входного файла приведён для пяти коробок и случая, когда минимальная допустимая разница между длинами сторон коробок, подходящих для упаковки «матрёшкой», составляет $3$ единицы. При таких исходных данных условию задачи удовлетворяют наборы коробок с длинами сторон $30$, $40$ и $43$ или $32$, $40$ и $43$ соответственно, т.е. количество коробок равно $3$, а длина стороны самой маленькой коробки равна $32$.

Отсортируем длины сторон по возрастанию. Матрёшка — это цепочка, в которой каждая следующая коробка больше предыдущей хотя бы на $10$. Максимальную длину даёт обычная жадность: идём по возрастанию и берём коробку, если она подходит к последней взятой.

Со вторым вопросом жадность не справляется: она начинает с самой маленькой коробки, а нам нужна самая большая из возможных стартовых. Поэтому считаем для каждой коробки $ln[i]$ — длину максимальной цепочки, которая начинается именно с неё.

Тут работает удобное свойство: чем меньше коробка, тем длиннее цепочка от неё, потому что любую цепочку, начинающуюся с большей коробки, можно начать и с меньшей. Значит $ln$ не возрастает по мере роста стороны, и максимум среди подходящих продолжений достигается на самой первой коробке со стороной не менее $a_i + 10$. Её и находим двоичным поиском, а массив заполняем справа налево.

Затем берём $K$ — наибольшее значение в $ln$, и среди всех коробок с таким значением выбираем самую большую сторону.

from bisect import bisect_left

f = open('26-08.txt')
n = int(f.readline())
a = sorted(int(f.readline()) for _ in range(n))

ln = [1] * n                        # длина макс. цепочки, начинающейся с i-й коробки
for i in range(n-1, -1, -1):
    j = bisect_left(a, a[i] + 10)   # первая коробка, в которую влезет i-я
    if j < n:
        ln[i] = 1 + ln[j]

K = max(ln)
smallest = max(a[i] for i in range(n) if ln[i] == K)

print(K, smallest)   # 935 51

Проверка. В файле $10000$ коробок со сторонами от $50$ до $9998$, жадный подсчёт тоже даёт цепочку из $935$ коробок. Файл тот же, что в задаче с разницей $3$, где ответ был $2767$ и $51$: при более жёстком шаге цепочка ожидаемо укоротилась почти втрое, а стартовая коробка осталась прежней. На типовом примере из условия с разницей $3$ программа выдаёт $3$ и $32$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
9. Задание #297700
Задание было решено верно
Задание было решено неверно

Отдел маркетинга сети продуктовых магазинов составляет рейтинг продуктов по информации об их сроках хранения с момента изготовления и после вскрытия упаковки. Для каждого продукта известен срок его хранения с момента изготовления и срок годности к употреблению после вскрытия упаковки. Продукты пронумерованы начиная с единицы.

В рейтинговом списке маркетологи располагают продукты по следующему алгоритму:

  • все $2N$ чисел, обозначающих срок хранения и срок годности к употреблению для $N$ продуктов, упорядочивают по возрастанию;
  • если минимальное число в этом упорядоченном списке – срок хранения, то продукт в рейтинге занимает первое свободное место от его начала;
  • если минимальное число – это срок годности к употреблению, то продукт занимает первое свободное место от конца рейтинга;
  • если число обозначает срок хранения или годности к употреблению уже рассмотренного продукта, то его не принимают во внимание.

Этот алгоритм применяется последовательно для размещения всех $N$ продуктов. Определите номер последнего продукта, для которого будет определено его место в рейтинге, и количество продуктов, которые займут в рейтинге более высокие места.

Входные данные

В первой строке входного файла находится натуральное число $N$ ($N \le 1000$) – количество продуктов. Следующие $N$ строк содержат пары чисел, обозначающих соответственно срок хранения продукта с момента изготовления и срок годности к употреблению после вскрытия упаковки (все числа натуральные, различные).

Запишите в ответе два натуральных числа: сначала номер последнего продукта, для которого будет определено его место в рейтинге, затем – количество продуктов, которые займут в списке более высокие места.

Типовой пример организации данных во входном файле:

5
30 50
100 155
150 170
10 160
120 55

При таких исходных данных порядок расположения продуктов в рейтинге следующий: $4$, $1$, $2$, $3$, $5$. Последним займёт своё место в рейтинге продукт $3$. При этом три продукта займут более высокие места.

Это прямое моделирование описанного алгоритма. Собираем все $2N$ чисел, помечая каждое двумя вещами: номером продукта и типом — срок хранения или срок годности. Сортируем по возрастанию и идём по списку.

Для очередного числа смотрим, размещён ли уже его продукт. Если да, число пропускаем. Если нет, то при типе «срок хранения» продукт встаёт на первое свободное место с начала, а при типе «срок годности» — на первое свободное с конца. Достаточно держать два указателя: front растёт от единицы, back убывает от $N$.

Последний обработанный таким образом продукт и есть ответ на первый вопрос, а количество продуктов выше него равно его позиции минус один.

f = open('26-09.txt')
n = int(f.readline())

nums = []
for i in range(1, n+1):
    a, b = map(int, f.readline().split())
    nums.append((a, i, 'A'))       # срок хранения
    nums.append((b, i, 'B'))       # срок годности
nums.sort()

placed = {}
front, back = 1, n
for _, i, t in nums:
    if i in placed:                # продукт уже размещён
        continue
    if t == 'A':
        placed[i] = front
        front += 1
    else:
        placed[i] = back
        back -= 1
    last, pos = i, placed[i]

print(last, pos - 1)   # 9 464

Проверка. Продуктов $972$, все они размещаются. Последним встаёт продукт номер $9$ со сроками $95109$ и $96164$ — его срок хранения оказался самым большим среди всех неразмещённых чисел. Он занимает позицию $465$, значит выше него стоят $464$ продукта. Предыдущие два шага заняли позиции $467$ и $466$ с конца, так что середина рейтинга сомкнулась ровно на нём. На типовом примере из условия программа выдаёт $3$ и $3$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
10. Задание #297697
Задание было решено верно
Задание было решено неверно

В магазине для упаковки подарков есть $N$ кубических коробок. Самой интересной считается упаковка подарка по принципу матрёшки – подарок упаковывается в одну из коробок, та в свою очередь в другую коробку и т.д. Одну коробку можно поместить в другую, если длина её стороны хотя бы на $7$ единиц меньше длины стороны другой коробки. Определите наибольшее количество коробок, которое можно использовать для упаковки одного подарка, и максимально возможную длину стороны самой маленькой коробки, где будет находиться подарок. Размер подарка позволяет поместить его в самую маленькую коробку.

Входные данные

В первой строке входного файла находится число $N$ – количество коробок в магазине (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения длин сторон коробок (все числа натуральные, не превышающие $10000$), каждое – в отдельной строке.

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

Типовой пример организации данных во входном файле:

5
43
40
32
40
30

Пример входного файла приведён для пяти коробок и случая, когда минимальная допустимая разница между длинами сторон коробок, подходящих для упаковки «матрёшкой», составляет $3$ единицы. При таких исходных данных условию задачи удовлетворяют наборы коробок с длинами сторон $30$, $40$ и $43$ или $32$, $40$ и $43$ соответственно, т.е. количество коробок равно $3$, а длина стороны самой маленькой коробки равна $32$.

Отсортируем длины сторон по возрастанию. Матрёшка — это цепочка, в которой каждая следующая коробка больше предыдущей хотя бы на $7$. Максимальную длину даёт обычная жадность: идём по возрастанию и берём коробку, если она подходит к последней взятой.

Со вторым вопросом жадность не справляется: она стартует с самой маленькой коробки, а нам нужна самая большая из возможных стартовых. Поэтому для каждой коробки считаем $ln[i]$ — длину максимальной цепочки, которая начинается именно с неё.

Работает удобное свойство: чем меньше коробка, тем длиннее цепочка от неё, потому что любую цепочку, начинающуюся с большей коробки, можно начать и с меньшей. Значит $ln$ не возрастает по мере роста стороны, и максимум среди подходящих продолжений достигается на самой первой коробке со стороной не менее $a_i + 7$. Её и находим двоичным поиском, а массив заполняем справа налево.

Затем берём $K$ — наибольшее значение в $ln$, и среди всех коробок с таким значением выбираем самую большую сторону.

from bisect import bisect_left

f = open('26-10.txt')
n = int(f.readline())
a = sorted(int(f.readline()) for _ in range(n))

ln = [1] * n                       # длина макс. цепочки, начинающейся с i-й коробки
for i in range(n-1, -1, -1):
    j = bisect_left(a, a[i] + 7)   # первая коробка, в которую влезет i-я
    if j < n:
        ln[i] = 1 + ln[j]

K = max(ln)
smallest = max(a[i] for i in range(n) if ln[i] == K)

print(K, smallest)   # 1306 52

Проверка. В файле $10000$ коробок со сторонами от $50$ до $9998$, жадный подсчёт тоже даёт цепочку из $1306$ коробок. Стартовать можно с коробок $50$, $51$ или $52$ — все три дают ровно $1306$ звеньев, а вот с $53$ получается уже только $1305$. Поэтому ответом идёт наибольшая из подходящих, то есть $52$. На типовом примере из условия с разницей $3$ программа выдаёт $3$ и $32$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
11. Задание #297704
Задание было решено верно
Задание было решено неверно

Входной файл содержит заявки пассажиров, желающих сдать свой багаж в камеру хранения. В заявке указаны время сдачи багажа и время освобождения ячейки (в минутах от начала суток). Багаж одного пассажира размещается в одной свободной ячейке с минимальным номером. Ячейки пронумерованы начиная с единицы. Размещение багажа в ячейке или её освобождение происходит в течение $1$ мин. Багаж можно поместить в только что освобождённую ячейку начиная со следующей минуты. Если в момент сдачи багажа свободных ячеек нет, то пассажир уходит. Определите, сколько пассажиров сможет сдать свой багаж в течение $24$ ч и какой номер будет иметь ячейка, которую займут последней. Если таких ячеек несколько, укажите минимальный номер ячейки.

Входные данные

В первой строке входного файла находится натуральное число $K$, не превышающее $1000$, – количество ячеек в камере хранения. Во второй строке – натуральное число $N$ ($N \le 1000$), обозначающее количество пассажиров. Каждая из следующих $N$ строк содержит два натуральных числа, каждое из которых не превышает $1440$: указанное в заявке время размещения багажа в ячейке и время освобождения ячейки (в минутах от начала суток).

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

Типовой пример организации данных во входном файле:

2
5
30 60
40 1000
59 60
61 1000
1010 1440

При таких исходных данных положить вещи в камеру хранения смогут первый, второй, четвёртый и пятый пассажиры. Последний пассажир положит вещи в ячейку $1$, так как ячейки $1$ и $2$ будут свободны.

Это прямое моделирование, оптимизировать ничего не нужно. Заявки в файле лежат вперемешку, поэтому сначала сортируем их по времени сдачи багажа — обслуживать пассажиров надо в порядке прихода.

Для каждой ячейки храним одно число: момент, когда она освобождается. Пассажир с временем прихода $t$ может занять ячейку, если она освободилась строго раньше, то есть если записанное для неё время меньше $t$. Это и есть формулировка «начиная со следующей минуты»: ячейка, освобождённая в минуту $60$, доступна с минуты $61$.

Перебираем ячейки по возрастанию номера и берём первую подходящую — так выполняется требование про минимальный номер. Если подходящей нет, пассажир уходит. Попутно считаем успешных пассажиров и запоминаем, кто занял ячейку последним по времени; при совпадении времени берём меньший номер ячейки.

f = open('26-11.txt')
K = int(f.readline())
N = int(f.readline())
req = [tuple(map(int, f.readline().split())) for _ in range(N)]
req.sort()                                # по времени сдачи багажа

free = [0] * K                            # время, когда ячейка освободится
cnt = 0
last_t, last_cell = -1, None

for t, e in req:
    for i in range(K):
        if free[i] < t:                   # доступна со следующей минуты
            free[i] = e
            cnt += 1
            if t > last_t:
                last_t, last_cell = t, i + 1
            elif t == last_t and i + 1 < last_cell:
                last_cell = i + 1
            break

print(cnt, last_cell)   # 389 133

Проверка. Ячеек $210$, заявок $987$, успешными оказались $389$ пассажиров. Последняя сдача багажа среди них произошла на $999$-й минуте, и такой пассажир был всего один — он занял ячейку $133$. На типовом примере из условия программа выдаёт $4$ и $1$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
12. Задание #297705
Задание было решено верно
Задание было решено неверно

Входной файл содержит сведения о заявках на проведение мероприятий в конференц-зале. В каждой заявке указаны время начала и время окончания мероприятия (в минутах от начала суток). Если время начала одного мероприятия меньше времени окончания другого, то провести можно только одно из них. Если время окончания одного мероприятия совпадает со временем начала другого, то провести можно оба. Определите, какое максимальное количество мероприятий можно провести в конференц-зале, и каков при этом максимально возможный перерыв между двумя последними мероприятиями.

Входные данные

В первой строке входного файла находится натуральное число $N$ ($N \le 1000$) – количество заявок на проведение мероприятий. Следующие $N$ строк содержат пары чисел, обозначающих время начала и время окончания мероприятий. Каждое из чисел натуральное, не превосходящее $1440$.

Запишите в ответе два числа: максимальное количество мероприятий и самый длинный перерыв между двумя последними мероприятиями (в минутах).

Типовой пример организации данных во входном файле:

5
10 150
100 120
131 170
150 180
120 130

При таких исходных данных можно провести максимум три мероприятия, например, мероприятия по заявкам $2$, $3$ и $5$. Максимальный перерыв между двумя последними мероприятиями составит $20$ мин., если состоятся мероприятия по заявкам $2$, $4$ и $5$.

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

Второй вопрос жадность не решает: расписаний с максимальным количеством мероприятий много, а перерыв нужен наибольший по всем таким расписаниям. Поэтому считаем динамику: для каждого мероприятия $i$ находим $cnt[i]$ — сколько мероприятий максимум умещается в цепочке, которая заканчивается именно этим. Максимум по всем $cnt$ даёт ответ на первый вопрос, обозначим его $K$.

Теперь пара последних мероприятий. Последнее — это любое $j$ с $cnt[j] = K$, а предыдущее — любое совместимое с ним $i$, у которого $cnt[i] = K-1$: тогда цепочка из $K-1$ мероприятий заканчивается на $i$, а $j$ добавляется последним. Перерыв равен разности между началом $j$ и концом $i$, берём наибольший.

f = open('26-12.txt')
n = int(f.readline())
ev = [tuple(map(int, f.readline().split())) for _ in range(n)]
ev.sort(key=lambda x: x[1])                  # по времени окончания

cnt = [0] * n            # макс. число мероприятий в цепочке, кончающейся i-м
for i, (a, b) in enumerate(ev):
    best = 0
    for k in range(i):
        if ev[k][1] <= a and cnt[k] > best:   # конец не позже начала
            best = cnt[k]
    cnt[i] = best + 1

K = max(cnt)

gap = 0
for j, (a, b) in enumerate(ev):
    if cnt[j] != K:                          # j должно быть последним в цепочке
        continue
    for i in range(j):
        if cnt[i] == K - 1 and ev[i][1] <= a:
            gap = max(gap, a - ev[i][1])

print(K, gap)   # 27 4

Проверка. Жадный подсчёт на том же файле тоже даёт $27$ мероприятий. Перерыв вышел совсем небольшим — всего $4$ минуты: заявки в файле плотные, и расписание из $27$ мероприятий почти не оставляет свободы на последнем шаге. На типовом примере из условия программа выдаёт $3$ и $20$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
13. Задание #298054
Задание было решено верно
Задание было решено неверно

В магазине для упаковки подарков есть $N$ кубических коробок. Самой интересной считается упаковка подарка по принципу матрёшки – подарок упаковывается в одну из коробок, та в свою очередь в другую коробку и т.д. Одну коробку можно поместить в другую, если длина её стороны хотя бы на $3$ единицы меньше длины стороны другой коробки. Определите наибольшее количество коробок, которое можно использовать для упаковки одного подарка, и максимально возможную длину стороны самой маленькой коробки, где будет находиться подарок. Размер подарка позволяет поместить его в самую маленькую коробку.

Входные данные

В первой строке входного файла находится число $N$ – количество коробок в магазине (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения длин сторон коробок (все числа натуральные, не превышающие $10000$), каждое – в отдельной строке.

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

Типовой пример организации данных во входном файле:

5
43
40
32
40
30

Пример входного файла приведён для пяти коробок и случая, когда минимальная допустимая разница между длинами сторон коробок, подходящих для упаковки «матрёшкой», составляет $3$ единицы. При таких исходных данных условию задачи удовлетворяют наборы коробок с длинами сторон $30$, $40$ и $43$ или $32$, $40$ и $43$ соответственно, т.е. количество коробок равно $3$, а длина стороны самой маленькой коробки равна $32$.

Отсортируем длины сторон по возрастанию. Матрёшка — это цепочка, в которой каждая следующая коробка больше предыдущей хотя бы на $3$. Максимальную длину даёт обычная жадность: идём по возрастанию и берём коробку, если она подходит к последней взятой.

Со вторым вопросом жадность не справляется: она начинает с самой маленькой коробки, а нам нужна самая большая из возможных стартовых. Поэтому считаем для каждой коробки $ln[i]$ — длину максимальной цепочки, которая начинается именно с неё.

Тут работает удобное свойство: чем меньше коробка, тем длиннее цепочка от неё, потому что любую цепочку, начинающуюся с большей коробки, можно начать и с меньшей. Значит $ln$ не возрастает по мере роста стороны, и максимум среди подходящих продолжений достигается на самой первой коробке со стороной не менее $a_i + 3$. Её и находим двоичным поиском, а массив заполняем справа налево.

Затем берём $K$ — наибольшее значение в $ln$, и среди всех коробок с таким значением выбираем самую большую сторону.

from bisect import bisect_left

f = open('26-13-2.txt')
n = int(f.readline())
a = sorted(int(f.readline()) for _ in range(n))

ln = [1] * n                       # длина макс. цепочки, начинающейся с i-й коробки
for i in range(n-1, -1, -1):
    j = bisect_left(a, a[i] + 3)   # первая коробка, в которую влезет i-я
    if j < n:
        ln[i] = 1 + ln[j]

K = max(ln)
smallest = max(a[i] for i in range(n) if ln[i] == K)

print(K, smallest)   # 2767 51

Проверка. В файле $10000$ коробок со сторонами от $50$ до $9998$, жадный подсчёт тоже даёт цепочку из $2767$ коробок. Цепочка, стартующая с коробки $51$, действительно содержит $2767$ штук, а если начать со следующей по размеру коробки $52$, выйдет только $2766$. На типовом примере из условия программа выдаёт $3$ и $32$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
14. Задание #298053
Задание было решено верно
Задание было решено неверно

Входной файл содержит сведения о заявках на проведение мероприятий в конференц-зале. В каждой заявке указаны время начала и время окончания мероприятия (в минутах от начала суток). Если время начала одного мероприятия меньше времени окончания другого, то провести можно только одно из них. Если время окончания одного мероприятия совпадает со временем начала другого, то провести можно оба. Определите, какое максимальное количество мероприятий можно провести в конференц-зале, и каков при этом максимально возможный перерыв между двумя последними мероприятиями.

Входные данные

В первой строке входного файла находится натуральное число $N$ ($N \le 1000$) – количество заявок на проведение мероприятий. Следующие $N$ строк содержат пары чисел, обозначающих время начала и время окончания мероприятий. Каждое из чисел натуральное, не превосходящее $1440$.

Запишите в ответе два числа: максимальное количество мероприятий и самый длинный перерыв между двумя последними мероприятиями (в минутах).

Типовой пример организации данных во входном файле:

5
10 150
100 120
131 170
150 180
120 130

При таких исходных данных можно провести максимум три мероприятия, например, мероприятия по заявкам $2$, $3$ и $5$. Максимальный перерыв между двумя последними мероприятиями составит $20$ мин., если состоятся мероприятия по заявкам $2$, $4$ и $5$.

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

Второй вопрос жадность не решает: расписаний с максимальным количеством мероприятий много, а перерыв нужен наибольший по всем таким расписаниям. Поэтому считаем динамику: для каждого мероприятия $i$ находим $cnt[i]$ — сколько мероприятий максимум умещается в цепочке, которая заканчивается именно этим. Максимум по всем $cnt$ даёт ответ на первый вопрос, обозначим его $K$.

Теперь пара последних мероприятий. Последнее — это любое $j$ с $cnt[j] = K$, а предыдущее — любое совместимое с ним $i$, у которого $cnt[i] = K-1$: тогда цепочка из $K-1$ мероприятий заканчивается на $i$, а $j$ добавляется последним. Перерыв равен разности между началом $j$ и концом $i$, берём наибольший.

f = open('26-14-2.txt')
n = int(f.readline())
ev = [tuple(map(int, f.readline().split())) for _ in range(n)]
ev.sort(key=lambda x: x[1])                  # по времени окончания

cnt = [0] * n            # макс. число мероприятий в цепочке, кончающейся i-м
for i, (a, b) in enumerate(ev):
    best = 0
    for k in range(i):
        if ev[k][1] <= a and cnt[k] > best:   # конец не позже начала
            best = cnt[k]
    cnt[i] = best + 1

K = max(cnt)

gap = 0
for j, (a, b) in enumerate(ev):
    if cnt[j] != K:                          # j должно быть последним в цепочке
        continue
    for i in range(j):
        if cnt[i] == K - 1 and ev[i][1] <= a:
            gap = max(gap, a - ev[i][1])

print(K, gap)   # 23 19

Проверка. Заявок $990$, жадный подсчёт на том же файле тоже даёт $23$ мероприятия. На типовом примере из условия программа выдаёт $3$ и $20$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
15. Задание #298052
Задание было решено верно
Задание было решено неверно

В магазине для упаковки подарков есть $N$ кубических коробок. Самой интересной считается упаковка подарка по принципу матрёшки – подарок упаковывается в одну из коробок, та в свою очередь в другую коробку и т.д. Одну коробку можно поместить в другую, если длина её стороны хотя бы на $11$ единиц меньше длины стороны другой коробки. Определите наибольшее количество коробок, которое можно использовать для упаковки одного подарка, и максимально возможную длину стороны самой маленькой коробки, где будет находиться подарок. Размер подарка позволяет поместить его в самую маленькую коробку.

Входные данные

В первой строке входного файла находится число $N$ – количество коробок в магазине (натуральное число, не превышающее $10000$). В следующих $N$ строках находятся значения длин сторон коробок (все числа натуральные, не превышающие $10000$), каждое – в отдельной строке.

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

Типовой пример организации данных во входном файле:

5
43
40
32
40
30

Пример входного файла приведён для пяти коробок и случая, когда минимальная допустимая разница между длинами сторон коробок, подходящих для упаковки «матрёшкой», составляет $3$ единицы. При таких исходных данных условию задачи удовлетворяют наборы коробок с длинами сторон $30$, $40$ и $43$ или $32$, $40$ и $43$ соответственно, т.е. количество коробок равно $3$, а длина стороны самой маленькой коробки равна $32$.

Отсортируем длины сторон по возрастанию. Матрёшка — это цепочка, в которой каждая следующая коробка больше предыдущей хотя бы на $11$. Максимальную длину даёт обычная жадность: идём по возрастанию и берём коробку, если она подходит к последней взятой.

Со вторым вопросом жадность не справляется: она стартует с самой маленькой коробки, а нам нужна самая большая из возможных стартовых. Поэтому для каждой коробки считаем $ln[i]$ — длину максимальной цепочки, которая начинается именно с неё.

Работает удобное свойство: чем меньше коробка, тем длиннее цепочка от неё, потому что любую цепочку, начинающуюся с большей коробки, можно начать и с меньшей. Значит $ln$ не возрастает по мере роста стороны, и максимум среди подходящих продолжений достигается на самой первой коробке со стороной не менее $a_i + 11$. Её и находим двоичным поиском, а массив заполняем справа налево.

Затем берём $K$ — наибольшее значение в $ln$, и среди всех коробок с таким значением выбираем самую большую сторону.

from bisect import bisect_left

f = open('26-15-1.txt')
n = int(f.readline())
a = sorted(int(f.readline()) for _ in range(n))

ln = [1] * n                        # длина макс. цепочки, начинающейся с i-й коробки
for i in range(n-1, -1, -1):
    j = bisect_left(a, a[i] + 11)   # первая коробка, в которую влезет i-я
    if j < n:
        ln[i] = 1 + ln[j]

K = max(ln)
smallest = max(a[i] for i in range(n) if ln[i] == K)

print(K, smallest)   # 854 54

Проверка. В файле $10000$ коробок со сторонами от $50$ до $9998$, жадный подсчёт тоже даёт цепочку из $854$ коробок. Стартовать можно с любой коробки от $50$ до $54$ — все дают ровно $854$ звена, поэтому в ответ идёт наибольшая из них. На типовом примере из условия с разницей $3$ программа выдаёт $3$ и $32$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
16. Задание #298064
Задание было решено верно
Задание было решено неверно

При онлайн-покупке билета на концерт известно, какие места в зале уже заняты. Необходимо купить два билета на такие соседние места в одном ряду, чтобы перед ними все кресла с такими же номерами были свободны, а ряд находился как можно дальше от сцены. Если в этом ряду таких пар мест несколько, найдите пару с наименьшими номерами. В ответе запишите два целых числа: искомый номер ряда и наименьший номер места в найденной паре. Нумерация рядов и мест ведётся с $1$. Гарантируется, что хотя бы одна такая пара в зале есть.

Входные данные

В первой строке входного файла находятся три числа: $N$ – количество занятых мест в зале (целое положительное число, не превышающее $10000$), $M$ – количество рядов (целое положительное число, не превышающее $100000$) и $K$ – количество мест в каждом ряду (целое положительное число, не превышающее $100000$). В следующих $N$ строках находятся пары натуральных чисел: номер ряда и номер места занятого кресла соответственно (первое число не превышает значения $M$, а второе – $K$).

Выходные данные

Два целых положительных числа: наибольший номер ряда и наименьший номер места в найденной паре кресел.

Типовой пример организации данных во входном файле:

7 7 8
1 1
6 6
5 5
6 7
4 4
2 2
3 3

При таких исходных данных ответом является пара чисел $5$ и $6$. Условию задачи удовлетворяют места $6$ и $7$ в ряду $5$: перед креслами $6$ и $7$ нет занятых мест и это первая из двух возможных пар в этом ряду. В рядах $6$ и $7$ искомую пару найти нельзя.

Условие «перед ними все кресла с такими же номерами свободны» устроено жёстче, чем в похожей задаче про одно место: там достаточно было свободного участка, а здесь свободными должны быть все ряды от первого. Значит для каждого номера места важна ровно одна величина — номер первого ряда, где это место занято. Обозначим её $first[p]$; если место $p$ не занято нигде, считаем $first[p] = M+1$.

Тогда пара мест $p$ и $p+1$ годится в ряду $r$ при условии $r < first[p]$ и $r < first[p+1]$, то есть $r \le \min(first[p], first[p+1]) — 1$. Обратите внимание, что сюда автоматически входит и требование «сами эти два кресла свободны»: если бы место $p$ было занято в самом ряду $r$, то $first[p] \le r$.

Дальше просто перебираем все пары соседних номеров мест и берём максимум этой величины. Ряд нужен как можно дальше от сцены, то есть с наибольшим номером; при совпадении берём наименьший номер места, что достигается перебором $p$ по возрастанию со строгим сравнением.

Перебирать сами кресла нельзя — их до десяти миллиардов. Массив $first$ имеет размер $K$, и этого достаточно.

f = open('26-16.txt')
N, M, K = map(int, f.readline().split())

first = [M+1] * (K+2)             # первый ряд, где место p занято
for _ in range(N):
    r, p = map(int, f.readline().split())
    if r < first[p]:
        first[p] = r

best_row, best_seat = 0, None
for p in range(1, K):             # пара соседних мест p и p+1
    r = min(first[p], first[p+1]) - 1
    if r > best_row:
        best_row, best_seat = r, p

print(best_row, best_seat)   # 21028 6660

Проверка. В файле $N = 9992$, $M = 99906$, $K = 6661$. Место $6660$ не занято ни в одном ряду, а место $6661$ впервые занято в ряду $21029$. Значит пара работает вплоть до ряда $21028$, и оба кресла в нём свободны. Другой пары с таким же номером ряда нет, так что выбор наименьшего номера места не понадобился. На типовом примере из условия программа выдаёт $5$ и $6$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
17. Задание #298065
Задание было решено верно
Задание было решено неверно

Входной файл содержит информацию о заявках граждан, обращающихся во многофункциональный центр (МФЦ) в течение календарных суток. В заявке указаны время начала и время окончания приёма специалистом (в минутах от начала суток). Рабочие места специалистов МФЦ (окна) пронумерованы натуральными числами начиная с $1$. Приём одного гражданина ведёт свободный специалист в окне с минимальным номером. Новый посетитель может обратиться к освободившемуся специалисту начиная со следующей минуты после завершения приёма предыдущего. Если в момент обращения в МФЦ свободных специалистов нет, то гражданин уходит. Определите, сколько граждан смогут попасть на приём в МФЦ в течение $24$ ч, и каков номер окна специалиста, который начнёт принимать посетителя последним. Если таких окон несколько, укажите наименьший номер окна.

Входные данные

В первой строке входного файла находится натуральное число $K$, не превышающее $1000$, – количество окон в МФЦ. Во второй строке – натуральное число $N$ ($N \le 10000$), обозначающее количество граждан. Каждая из следующих $N$ строк содержит два натуральных числа, каждое из которых не превышает $1440$: указанные в заявке время начала и время окончания приёма (в минутах от начала суток).

Запишите в ответе два числа: количество граждан, которые смогут воспользоваться услугами МФЦ, и номер окна, в котором специалист примет последнего гражданина.

Типовой пример организации данных во входном файле:

2
5
30 60
40 100
59 60
61 100
101 144

При таких исходных данных воспользоваться услугами МФЦ смогут первый, второй, четвёртый и пятый граждане. Наименьший номер окна, где последний из граждан будет принят специалистом, – $1$, так как будут свободны окна $1$ и $2$.

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

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

f = open('26-17.txt')
K = int(f.readline())
N = int(f.readline())
req = [tuple(map(int, f.readline().split())) for _ in range(N)]
req.sort()                                # по времени обращения

free = [0] * K                            # время, когда окно освободится
cnt = 0
last_t, last_win = -1, None

for t, e in req:
    for i in range(K):
        if free[i] < t:                   # свободно со следующей минуты
            free[i] = e
            cnt += 1
            if t > last_t:
                last_t, last_win = t, i + 1
            elif t == last_t and i + 1 < last_win:
                last_win = i + 1
            break

print(cnt, last_win)   # 793 2

Проверка. Окон $267$, заявок $994$, на приём попали $793$ гражданина. Последнее обращение среди них произошло на $1437$-й минуте, и такой гражданин был один — его принял специалист в окне $2$. На типовом примере из условия программа выдаёт $4$ и $1$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
18. Задание #298066
Задание было решено верно
Задание было решено неверно

Во время сессии студенты сдают $4$ экзамена, за каждый из которых можно получить от $2$ до $5$ баллов. Студенты, получившие хотя бы одну «двойку», считаются не сдавшими сессию. Результаты сессии публикуются в виде рейтингового списка, в котором сначала указаны идентификационные номера студентов (ID), сдавших сессию, в порядке убывания среднего балла за сессию, а в случае равенства средних баллов – в порядке возрастания ID. Затем располагаются ID студентов, не сдавших сессию: сначала – получивших одну «двойку», затем – две «двойки», потом ID студентов с тремя «двойками» и, наконец, ID студентов, получивших по $2$ балла за каждый из экзаменов. Если студенты имеют одинаковое количество «двоек», то их ID в рейтинге располагаются в порядке возрастания.

Повышенную стипендию получают студенты, занявшие в рейтинговом списке первые $25,%$ мест, при условии отсутствия у них «двоек». Гарантируется, что без «двоек» сессию сдали не менее $25,%$ студентов. Найдите ID студента, который занимает последнее место среди студентов с повышенной стипендией, а также ID первого в рейтинговом списке студента, который имеет более двух «двоек».

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

Входные данные

В первой строке входного файла находится число $N$, обозначающее количество студентов (целое положительное число, не превышающее $10000$). Каждая из следующих $N$ строк содержит $5$ чисел через пробел: ID студента (целое положительное число, не превышающее $100000$) и четыре оценки, полученные им за сессию. Гарантируется, что общее число студентов $N$ кратно $4$ и хотя бы один студент имеет более двух «двоек». Во входном файле все ID различны.

Выходные данные

Два натуральных числа: искомые ID студентов в порядке, указанном в условии задачи.

Типовой пример организации данных во входном файле:

8
4 4 4 4 4
7 5 5 5 2
10 3 4 4 5
1 4 4 4 3
6 3 5 5 3
2 2 2 2 2
13 2 2 2 3
3 3 3 3 3

При таких исходных данных рейтинговый список ID имеет вид: $4$ $6$ $10$ $1$ $3$ $7$ $13$ $2$. Ответ: $6$ $13$.

Строить весь рейтинг целиком не обязательно, но проще всего именно так и сделать — он собирается из двух независимо отсортированных частей.

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

Вторая часть: студенты с «двойками». Сортируем по количеству «двоек» по возрастанию, при равенстве — по ID. Ровно так и описан порядок в условии: сначала одна «двойка», потом две, три и четыре.

Дальше два ответа. Повышенную стипендию получают первые $N/4$ мест, и по условию гарантируется, что все они попадают в первую часть. Значит нужен элемент рейтинга с номером $N/4$, то есть индекс $N/4 — 1$. Второй ответ — первый в списке студент с более чем двумя «двойками», то есть первый элемент второй части, у которого «двоек» три или четыре.

f = open('26-18.txt')
n = int(f.readline())

passed, failed = [], []
for _ in range(n):
    v = list(map(int, f.readline().split()))
    sid, marks = v[0], v[1:]
    twos = marks.count(2)
    if twos == 0:
        passed.append((-sum(marks), sid))   # балл по убыванию, ID по возрастанию
    else:
        failed.append((twos, sid))          # число двоек, затем ID

passed.sort()
failed.sort()
rating = [sid for _, sid in passed] + [sid for _, sid in failed]

top = rating[n//4 - 1]                                    # последнее место среди 25 %
first_bad = next(sid for twos, sid in failed if twos > 2)

print(top, first_bad)   # 52326 635

Проверка. Студентов $9964$, из них без «двоек» — $6682$, что заметно больше четверти, так что граница стипендии действительно попадает в первую часть. Четверть мест — это $2491$, и на этом месте стоит студент с ID $52326$ и суммой баллов $17$; соседи по рейтингу имеют ту же сумму, но ID $52268$ и $52380$, то есть тай-брейк по возрастанию ID здесь сработал. С тремя «двойками» в файле $195$ студентов, с четырьмя — $15$, и первый из них по ID — $635$. На типовом примере из условия программа выдаёт $6$ и $13$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
19. Задание #298073
Задание было решено верно
Задание было решено неверно

Входной файл содержит сведения о массе грузов, поступивших в транспортную компанию, и о параметрах контейнеров, которые у неё имеются. В один контейнер может быть упакован только один груз. Найдите способ для распределения максимального количества грузов по контейнерам. Если способов несколько, то нужно выбрать такой, чтобы можно было упаковать наиболее тяжёлый груз.

Входные данные

В первой строке входного файла находятся два натуральных числа $N$ ($N \le 1000$) и $M$ ($M \le 1000$) – количество грузов и количество контейнеров соответственно. Следующие $N$ строк содержат числа, обозначающие массы грузов, затем идут $M$ строк, где указана максимально допустимая масса груза для размещения в конкретном контейнере. Числа $M$ и $N$ могут быть не равны.

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

Типовой пример организации данных во входном файле:

5 6
160
130
120
150
100
150
50
155
99
100
170

При таких исходных данных максимальное количество грузов, которые могут быть упакованы в контейнеры, равно $4$. При этом масса самого тяжёлого груза составит $160$, а упакованными окажутся грузы массой, например, $160$, $130$, $120$ и $100$ – в контейнеры, выдерживающие массу $170$, $150$, $155$ и $100$.

Первая часть — жадность. Отсортируем и грузы, и контейнеры по возрастанию, затем пройдём по контейнерам от меньшего к большему, каждый раз пытаясь положить в него самый лёгкий ещё не упакованный груз. Если он влезает, груз упакован, переходим к следующему. Это даёт максимальное количество, обозначим его $K$.

Вторая часть требует отдельной проверки. Спрашивается не про самый тяжёлый груз какого-то одного оптимального распределения, а про максимально возможный среди всех распределений размера $K$. Идём по грузам от самого тяжёлого к более лёгким и для каждого проверяем: можно ли включить его в распределение, не потеряв в количестве.

Тут важна деталь — какой контейнер отдать кандидату. Отдавать надо наименьший из подходящих, то есть первый контейнер с грузоподъёмностью не меньше массы кандидата. Большие контейнеры полезнее для остальных грузов, поэтому забирать их из общего пула невыгодно. После этого пересчитываем жадность на оставшихся грузах и контейнерах: если получилось ровно $K-1$, кандидат подходит, и это ответ.

from bisect import bisect_left

def match(goods, cans):                      # макс. число упакованных грузов
    i, cnt = 0, 0
    for c in cans:                           # контейнеры по возрастанию
        if i < len(goods) and goods[i] <= c:
            cnt += 1
            i += 1
    return cnt

f = open('26-19.txt')
n, m = map(int, f.readline().split())
goods = sorted(int(f.readline()) for _ in range(n))
cans  = sorted(int(f.readline()) for _ in range(m))

K = match(goods, cans)

best = None
for idx in range(len(goods)-1, -1, -1):      # кандидат на самый тяжёлый груз
    w = goods[idx]
    j = bisect_left(cans, w)                 # наименьший подходящий контейнер
    if j == len(cans):
        continue
    if match(goods[:idx] + goods[idx+1:], cans[:j] + cans[j+1:]) == K - 1:
        best = w
        break

print(K, best)   # 791 197491

Проверка. Грузов $853$ массой от $91534$ до $199595$, контейнеров $796$ грузоподъёмностью от $90045$ до $197604$. Упаковать удаётся $791$ груз. Девять самых тяжёлых грузов, начиная с $198262$, не помещаются ни в один контейнер вообще, поэтому кандидатом становится следующий по массе — $197491$, и для него подходящий контейнер находится. На типовом примере из условия программа выдаёт $4$ и $160$.

Показать
Очки опыта 20
Спросить Зави
Сообщить о проблеме
20. Задание #298074
Задание было решено верно
Задание было решено неверно

Сервер выполняет запросы на передачу данных, при этом сведения о каждом выполненном запросе (время регистрации, идентификатор клиента и объём переданных данных) сохраняются в журнале работы, а сам запрос – в специальном разделе памяти сервера, имеющем ограниченный объём. Каждый раз, когда в специальном разделе остаётся недостаточно свободной памяти, сервер создаёт резервную копию всех накопленных там данных, после чего освобождает раздел и продолжает выполнение запросов. Напишите программу для обработки журнала работы сервера и с её помощью определите идентификатор клиентского устройства, с которого на сервер был передан наибольший суммарный объём данных не позднее $11{:}59{:}59$, а также сумму объёмов двух наибольших резервных копий специального раздела (в Кбайт).

Входные данные

Первая строка входного файла (журнала работы сервера) содержит два натуральных числа: $N$ ($N < 1000000$) – количество строк в журнале и $K$ ($K < 1000000$) – вместимость специального раздела памяти сервера в Кбайт. Каждая из следующих $N$ строк содержит информацию об одном выполненном запросе: время регистрации запроса в формате ЧЧ:ММ:СС (часы, минуты, секунды) и два натуральных числа: $C$ ($C < 1000000$) – идентификатор клиентского устройства и $S$ ($S < K$) – объём данных запроса в Кбайт.

Выходные данные

В ответе запишите два числа: сначала идентификатор устройства, с которого на сервер был передан наибольший суммарный объём данных не позднее $11{:}59{:}59$, а затем сумму объёмов двух наибольших резервных копий специального раздела (в Кбайт).

Типовой пример организации данных во входном файле:
8 140000
01:01:01 101 20000
03:03:03 202 110000
05:05:05 101 90000
07:07:07 303 62000
10:10:10 101 48000
15:15:15 202 12000
21:21:21 303 120000
23:23:23 404 134000

При таких исходных данных резервное копирование специального раздела выполняется четыре раза: в $05{:}05{:}05$ (в объёме $130000$ Кбайт), в $07{:}07{:}07$ (в объёме $90000$ Кбайт), в $21{:}21{:}21$ (в объёме $122000$ Кбайт) и в $23{:}23{:}23$ (в объёме $120000$ Кбайт). Ответ для приведённого примера: $101$ $252000$.

Задача распадается на две независимые части, которые считаются за один проход по журналу.

Первая — моделирование раздела памяти. Держим счётчик накопленного объёма. Для очередного запроса проверяем, влезает ли он: если накопленное плюс новый объём превышает вместимость $K$, сервер сначала делает резервную копию того, что уже лежит в разделе, и обнуляет счётчик, и только потом кладёт туда новый запрос. Обратите внимание на порядок: в копию попадает объём до добавления текущего запроса. В примере это хорошо видно — в $05{:}05{:}05$ копируются $130000$ Кбайт, накопленные первыми двумя запросами, а сам запрос на $90000$ уже начинает новый цикл.

Вторая — суммы по клиентам. Складываем объёмы по идентификаторам, но только для запросов не позднее $11{:}59{:}59$. Время удобно сравнивать прямо как строки: формат ЧЧ:ММ:СС с ведущими нулями упорядочен лексикографически так же, как хронологически, поэтому разбирать его на числа не нужно.

from collections import defaultdict

f = open('26-20.txt')
n, K = map(int, f.readline().split())

total = defaultdict(int)
backups = []
cur = 0

for _ in range(n):
    t, c, s = f.readline().split()
    s = int(s)
    if cur + s > K:                  # свободной памяти не хватает
        backups.append(cur)          # резервная копия накопленного
        cur = 0
    cur += s
    if t <= '11:59:59':              # строки в формате ЧЧ:ММ:СС сравниваются как время
        total[int(c)] += s

backups.sort(reverse=True)
best = max(total, key=lambda c: total[c])

print(best, backups[0] + backups[1])   # 9517 46436

Проверка. В журнале $15005$ записей, вместимость раздела $23218$ Кбайт, резервных копий получилось $1116$. Две наибольшие оказались по $23218$ Кбайт каждая, то есть ровно под завязку, в сумме $46436$. По клиентам до полудня лидирует устройство $9517$ с объёмом $134167$ Кбайт, следующее за ним — $6877$ со $121879$. На типовом примере из условия программа выдаёт $101$ и $252000$.

Показать
Очки опыта 20
Спросить Зави
03:50:00
Решено заданий: 0 из
0 заданий сегодня