26. Прикладная задача: #298089
Сервер выполняет запросы на передачу данных, при этом сведения о каждом выполненном запросе (время регистрации, идентификатор клиента и объём переданных данных) сохраняются в журнале работы, а сам запрос – в специальном разделе памяти сервера, имеющем ограниченный объём. Каждый раз, когда в специальном разделе остаётся недостаточно свободной памяти, сервер создаёт резервную копию всех накопленных там данных, после чего освобождает раздел и продолжает выполнение запросов. Напишите программу для обработки журнала работы сервера и с её помощью определите идентификатор клиентского устройства, с которого на сервер был передан наибольший суммарный объём данных, не превышающий $150000$ Кбайт, а также сумму объёмов двух наибольших резервных копий специального раздела (в Кбайт), выполненных не ранее $12{:}00{:}00$.
Обе величины считаются за один проход, но у каждой свой фильтр — и оба надо применить аккуратно.
По клиентам суммы копятся за все сутки, без ограничения по времени. Зато при выборе победителя действует потолок: нужен наибольший объём среди тех, что не превышают $150000$ Кбайт. Это не «максимум минус что-то», а именно максимум по отфильтрованному множеству — клиентов с бо́льшим объёмом мы просто не рассматриваем. В примере из условия видно, как это работает: лидер по объёму — устройство $303$ со $182000$, но оно за потолком, и ответом становится $404$ со $134000$.
Моделирование раздела памяти прежнее: если накопленное плюс новый запрос превышает вместимость $K$, сервер копирует то, что уже лежит в разделе, обнуляет счётчик и кладёт туда новый запрос. В копилку кандидатов на две наибольшие копии попадают только те, что сделаны не ранее $12{:}00{:}00$. Время сравниваем прямо как строки: формат ЧЧ:ММ:СС с ведущими нулями упорядочен лексикографически так же, как хронологически.
from collections import defaultdict
f = open('26-26.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: # свободной памяти не хватает
if t >= '12:00:00': # копия сделана не ранее 12:00:00
backups.append(cur)
cur = 0
cur += s
total[int(c)] += s
best = max((v for v in total.values() if v <= 150000))
client = min(c for c, v in total.items() if v == best)
backups.sort(reverse=True)
print(client, backups[0] + backups[1]) # 1006 46566
Проверка. В журнале $15003$ записи, вместимость раздела $23285$ Кбайт. Копий всего $1112$, из них после полудня — $564$; две наибольшие оказались по $23285$ и $23281$ Кбайт, в сумме $46566$. Максимум по всем клиентам вообще равен $239933$ Кбайт, но он выше потолка; наибольший подходящий объём — $148122$ Кбайт у устройства $1006$. На типовом примере из условия программа выдаёт $404$ и $242000$.