Сдача без мелочи
Условие
В школьном буфете цены на булочки уже выписаны в список по возрастанию. У тебя есть купюра на сумму X, и ты хочешь купить ровно две булочки так, чтобы отдать деньги в точности без сдачи.
Номера булочек считаются с 1 в том порядке, в котором они стоят в списке.
Если подходящих пар несколько, буфетчица просит назвать пару номеров лексикографически минимальную: сначала минимальный i, а при равенстве — минимальный j.
Формат ввода
Первая строка: два целых числа n и X — количество цен и нужная сумма. Вторая строка: n целых чисел a1, a2, ..., an — цены булочек в неубывающем порядке.
Формат вывода
Если подходящей пары нет, выведи NO. Иначе выведи YES и на следующей строке два числа i j (1 ≤ i < j ≤ n) — номера булочек, дающие сумму X, причём пара должна быть лексикографически минимальной.
Ограничения
2 ≤ n ≤ 35000-10^9 ≤ ai ≤ 10^9- список цен отсортирован:
a1 ≤ a2 ≤ ... ≤ an Xможет быть большим по модулю (используй 64-битные целые; в Python это не проблема)
Пример
Ввод:
6 10
1 2 4 6 6 9
Вывод:
YES
1 6Как решать — идея подхода
Приём: Два указателя на отсортированном массиве
Ключевое наблюдение: цены уже отсортированы. Значит, если взять левую булочку i и правую j, то при увеличении i сумма a[i]+a[j] не уменьшится, а при уменьшении j сумма не увеличится. Это позволяет искать пару за один проход двумя указателями.
Почему работает: мы всегда «двигаем» ту сторону, которая может приблизить сумму к X, и никогда не пропускаем возможное решение, потому что порядок фиксирует направление изменения суммы.
План:
- Поставь i = 0 (самая дешёвая) и j = n-1 (самая дорогая).
- Пока i < j:
- s = a[i] + a[j].
- Если s < X, нужно увеличить сумму → i += 1.
- Если s > X, нужно уменьшить сумму → j -= 1.
- Если s == X, пара с этим i уже имеет минимальный i среди всех решений (мы дошли до неё, двигая i только вверх). Осталось сделать j минимальным при фиксированном i: пока можно, сдвигай j влево, если сумма всё ещё X, например:
while j-1 > i and a[i] + a[j-1] == X: j -= 1. - Выведи YES и (i+1, j+1).
- Если цикл закончился без находки — выведи NO.
Сложность по времени: O(n), память O(1).
Частая ошибка: остановиться на первом s==X и сразу печатать ответ. Из-за повторов (одинаковых цен) это может дать не минимальный j, а задача требует лексикографически минимальную пару (сначала минимальный i, потом минимальный j).
Разберись руками
Есть 6 цен по возрастанию: 1 2 4 6 6 9. Нужно найти ровно две булочки, чтобы сумма была 10, и вывести их номера (с 1).
- Отметь номера булочек (от 1 до 6), у которых цена равна 9.
- Если взять самую левую булочку №1 (цена 1) и самую правую булочку №6 (цена 9), какая получится сумма?
- Прогони «два пальца»: левый палец на первом элементе, правый — на последнем. После каждого события запиши состояние.
Идея: Держим два указателя на отсортированном списке: один слева, другой справа. Считаем сумму двух цен и по сравнению с нужной суммой решаем, какой указатель сдвигать, пока не найдём ровное совпадение или пока указатели не встретятся.
Решить задачу с автопроверкой на Python →
Куда дальше
- С нуля до олимпиады: маршрут — сколько занимает язык, какие приёмы нужны и к какому этапу это ведёт
- БВИ по олимпиадам: в какие вузы берут — правила приёма вузов, разобранные построчно, со ссылкой на приказ у каждой строки
- Перечневые олимпиады: что это и что дают — весь перечень Минобрнауки: уровни, срок диплома, разрезы по предметам и классам