26. Прикладная задача: #298078
Каждый кандидат в отряд космонавтов проходит $3$ испытания, за каждое из которых можно получить от $0$ до $100$ баллов. Кроме того, можно получить дополнительно от $0$ до $10$ баллов по итогам собеседования. Каждому кандидату присваивается уникальный идентификационный номер (ID) – натуральное число, не превышающее $100000$. В отряде имеется фиксированное число мест, на которые кандидаты зачисляются в порядке убывания их номера в рейтинговом списке. Рейтинговый список формируется по убыванию суммы набранных баллов, включая баллы за собеседование. При равенстве сумм баллов в рейтинговом списке выше стоит участник с бо́льшими баллами за собеседование, а при равенстве и этих баллов – с меньшим ID. Минимальная сумма баллов, с которой зачисляются в отряд все, её набравшие, называется проходным баллом. Гарантируется, что всегда есть участники, набравшие проходной балл.
Если после зачисления всех кандидатов с проходным баллом в отряде остались места, на которые претендуют несколько кандидатов с одинаковой суммой баллов, то такая сумма баллов называется полупроходным баллом, в противном случае полупроходной балл отсутствует.
В ответе запишите два целых числа: сначала ID кандидата, который последним из рейтингового списка набрал проходной балл, затем количество кандидатов, набравших полупроходной балл. Если полупроходной балл отсутствует, то второе число в ответе должно быть равно нулю.
Сначала строим рейтинг. Сортировка тройная: сумма всех четырёх баллов по убыванию, затем баллы за собеседование по убыванию, затем ID по возрастанию. Чтобы обойтись одной обычной сортировкой, кладём в ключ сумму и собеседование со знаком минус, а ID как есть.
Дальше ключевой момент — определение проходного балла. Он не равен просто баллу кандидата, стоящего на $K$-й строчке рейтинга: по условию это минимальная сумма, с которой зачисляются все её набравшие. Поэтому идём по рейтингу группами кандидатов с одинаковой суммой и берём группу целиком, только если она полностью помещается в оставшиеся места. Как только очередная группа не влезает, останавливаемся. Последний зачисленный кандидат и есть ответ на первый вопрос.
Та самая группа, которая не поместилась, и даёт полупроходной балл — при условии, что места ещё остались. Если после зачисления всех с проходным баллом отряд заполнен ровно или кандидаты кончились, полупроходного балла нет и в ответ идёт ноль.
f = open('26-23.txt')
n, K = map(int, f.readline().split())
c = []
for _ in range(n):
v = list(map(int, f.readline().split()))
c.append((-(v[1] + v[2] + v[3] + v[4]), -v[4], v[0])) # сумма, собеседование, ID
c.sort()
admitted, i, last = 0, 0, None
while i < n:
j = i
while j < n and c[j][0] == c[i][0]: # группа с одинаковой суммой
j += 1
if admitted + (j - i) > K: # группа целиком не влезает
break
admitted, last, i = j, c[j-1][2], j
half = (j - i) if (i < n and admitted < K) else 0
print(last, half) # 45539 127
Проверка. Кандидатов $9996$, мест $1076$. Проходной балл равен $280$, его и все более высокие набрали $955$ человек, последний из них — ID $45539$. Остаётся $121$ место, а на него претендуют $127$ кандидатов с суммой $279$ — это и есть полупроходной балл. На типовом примере из условия программа выдаёт $6$ и $3$.