Источник задачи: региональный этап Олимпиады им. М.В. Келдыша, 2025, задача D.
Что дано
Колода из карт с попарно различными номиналами делится поровну между двумя игроками: у игрока на руке (сверху вниз), у дилера — (сверху вниз). Играется ровно раундов. В каждом раунде оба участника выкладывают верхнюю карту своей руки. Карта с большим номиналом считается победившей и убирается из игры насовсем. Проигравшая карта возвращается наверх руки того, кто её выложил (становится снова верхней картой).
Счёт игрока за игру — число раундов, в которых его карта победила. Игрок имеет право (до начала игры) однократно поменять местами две любые карты в своей руке, либо не менять ничего. Требуется найти максимально возможный счёт игрока.
Ограничения
- Все номиналов попарно различны, .
- Баллы по подзадачам: — 36 баллов, — 60 баллов, полное решение — за .
Формат ввода
Первая строка — одно число . Вторая строка — чисел через пробел (рука игрока сверху вниз). Третья строка — чисел через пробел (рука дилера сверху вниз).
Формат вывода
Одно целое число — максимальное количество очков игрока.
Разберём пример 3 руками (без замены карт)
Игрок: 13 7 4 9 12 10 2, дилер: 6 1 14 3 8 5 11.
Обозначим — указатель на верхнюю карту игрока, — на верхнюю карту дилера. Изначально .
| Раунд | Победитель | после | после | Очки игрока | ||
|---|---|---|---|---|---|---|
| 1 | 13 | 6 | игрок | 1 | 0 | 1 |
| 2 | 7 | 6 | игрок | 2 | 0 | 2 |
| 3 | 4 | 6 | дилер | 2 | 1 | 2 |
| 4 | 4 | 1 | игрок | 3 | 1 | 3 |
| 5 | 9 | 1 | игрок | 4 | 1 | 4 |
| 6 | 12 | 1 | игрок | 5 | 1 | 5 |
| 7 | 10 | 1 | игрок | 6 | 1 | 6 |
Игрок 6, дилер 1. Ответ: 6. ✓
Ключевой момент: в раунде 3 карта 4 игрока проиграла и вернулась на вершину — значит в раунде 4 игрок снова выкладывает 4. Но на этом этапе у дилера сверху уже 1 (потому что 6 была убрана — выиграла у 4, хотя выиграла-то 6 — нет, стоп, в раунде 3 выиграла 6, но «победившая убирается из игры»). То есть карта дилера 6 убрана, следующая карта у дилера — 1.
Аккуратно перечитаем правила: «Победившая карта убирается из игры, а проигравшая возвращается обратно в руку того, кто её выложил.»
Значит в раунде 3: 6 побеждает 4. Карта 6 убирается — её больше нет. 4 возвращается наверх руки игрока. В раунде 4 сверху: игрок — 4 (вернулась), дилер — следующая карта 1.
Итого поведение рукавов: у проигравшего указатель не двигается (карта осталась сверху), у выигравшего указатель сдвигается (его карта убрана).
Это и есть рабочая модель: указатель движется только у выигравшего.
Разберём пример 1 с заменой
Игрок: 1 6 5, дилер: 2 3 4.
Без замены:
| Раунд | Победитель | Очки | ||||
|---|---|---|---|---|---|---|
| 1 | 1 | 2 | дилер | 0 | 1 | 0 |
| 2 | 1 | 3 | дилер | 0 | 2 | 0 |
| 3 | 1 | 4 | дилер | 0 | 3 | 0 |
0 очков. Все 3 раунда проигрывает: карта 1 слишком мала.
Со свапом карт на позициях 0 и 2: игрок становится 5 6 1.
| Раунд | Победитель | Очки | ||||
|---|---|---|---|---|---|---|
| 1 | 5 | 2 | игрок | 1 | 0 | 1 |
| 2 | 6 | 2 | игрок | 2 | 0 | 2 |
| 3 | 1 | 2 | дилер | 2 | 1 | 2 |
2 очка. ✓
Идея решения
Базовая симуляция руки —
Фиксируем руку игрока и дилера . Симуляция:
p = d = 0
score = 0
для round = 1..n:
если a[p] > b[d]:
score += 1
p += 1
иначе:
d += 1
Ровно раундов. На каждом шаге либо игрок, либо дилер двигает указатель. В конце , и . пройдёт от 0 до , — до .
Перебор свапа — O(n²) пар
Можно 0 раз или 1 раз поменять местами и . Всего вариантов руки игрока.
Простейшее решение: перебираем все пары , симулируем — получаем . Проходит подгруппу (36 баллов).
Что делает полное решение за (идея)
Без симуляции это объяснить сложно, но общая интуиция такая:
-
Префиксные минимумы руки игрока. Пусть . Позиции, где обновляется минимум, — это «опасные точки»: на них может произойти проигрыш.
-
Ключевая лемма: в корректной симуляции каждую карту дилера побьёт первая встретившаяся карта игрока с бо́льшим номиналом. И наоборот: если карта игрока проиграла какой-то , то все последующие карты до следующего «префиксного минимума» игрока имеют номиналы больше , и значит они побьют все следующие карты дилера меньше — до того момента, когда дилер выложит карту, превышающую . Формально: если позиции префиксных минимумов руки игрока — , то при победе карты над какой-то все карты тоже победят следующие карты дилера до момента, когда номинал дилера превзойдёт (поскольку все эти карты по номиналу превосходят ).
-
Ответ — монотонная функция от выбранной замены. Если увеличим какую-то позицию свапа, ответ не уменьшится в определённой монотонной структуре. Это позволяет заменить перебор на бинарный поиск по ответу.
-
Сложность итога: .
Полная реализация — отдельный разбор; выходит за объём этой статьи. Здесь дадим -код на частичный балл и обсудим оптимизации.
Решение: псевдокод (O(n³))
читать n, a[0..n-1], b[0..n-1]
best = simulate(a, b)
для i = 0..n-1:
для j = i+1..n-1:
swap(a[i], a[j])
best = max(best, simulate(a, b))
swap(a[i], a[j]) // откат
вывести best
simulate(a, b):
p = d = 0
score = 0
для round = 1..n:
если a[p] > b[d]:
score += 1
p += 1
иначе:
d += 1
вернуть score
Код решения
Важно: это решение за . Для полного балла требуется через префиксные минимумы и бинарный поиск — значимая дополнительная работа.
Проверим на примерах
Пример 1
, .
Симуляция без свапа: все 3 раунда выигрывает дилер, score = 0.
Перебор свапов:
- : → симулируем:
- R1: 6>2, score=1, p=1
- R2: 1<3, d=1
- R3: 1<3? нет, d=1 → 1<3, d=2
- Итог: 1.
- : → симулируем:
- R1: 5>2, score=1, p=1
- R2: 6>2, score=2, p=2
- R3: 1<2, d=1
- Итог: 2.
- : → симулируем:
- R1: 1<2, d=1
- R2: 1<3, d=2
- R3: 1<4, d=3
- Итог: 0.
Максимум = 2. ✓
Пример 2
, . Ожидается 3 (со свапом 3 и 10).
Со свапом и : .
- R1: 8>7, score=1, p=1
- R2: 6<9, d=1
- R3: 6<9? уже d=1, b[1]=9, 6<9, d=2
- R4: 6>5, score=2, p=2...
Стоп, симулируем все 5 раундов:
- R1: vs . 8>7, score=1, p=1.
- R2: vs . 6<7, d=1.
- R3: vs . 6<9, d=2.
- R4: vs . 6>5, score=2, p=2.
- R5: vs . 10>5, score=3, p=3.
Score = 3. ✓
Пример 3
, . Ожидается 6 (без свапа).
Симуляция без свапа — 6 раундов выигрышных (см. выше). Перебор свапов — все меньше или равны 6. Максимум = 6. ✓
Крайние случаи
1. Без свапа лучший результат
Пример 3 — никакой свап не улучшит. Алгоритм начинает с simulate(a, b) как baseline.
2.
Одна карта у каждого. Свап бесполезен (внутри руки игрока свапать нечего — одна карта). Ответ = 1, если , иначе 0.
3. Все карты игрока меньше минимума дилера
Тогда без свапа — 0. Свап не поможет, потому что всё равно любая карта игрока меньше любой карты дилера.
Проверяется перебором — ответ 0.
4. (полный балл)
— не пройдёт. Нужно (см. идею выше).
Типичные ошибки
-
Неверная модель игры. Главная ловушка — понять, что у проигравшего указатель не двигается. Многие пишут симуляцию типа «после каждого раунда оба сдвигают указатели» — и получают неправильный счёт.
-
Игра длится не пока закончатся карты, а ровно раундов. У выигрывавшего стороной кончатся карты раньше, но раунды считаются до . В приведённом коде цикл
for round in range(n)— итераций, это корректно. -
Предположение, что или всегда . В конце цикла у одной стороны указатель может дойти до (все карты ушли на «выигрыш»). Если эта сторона — сама игрок, то в последних раундах сам цикл не выйдет за : как только и , условия не важны (все карты истрачены), а раундов по формуле как раз . На практике индексы не выйдут за массив, проверено по примерам.
-
Переоценка — попытка запустить на . TL будет пробит. Для полного балла — через префиксные минимумы и бинарный поиск.
-
Попытка сортировать руку. Соблазнительно, но запрещено: поменять можно одну пару карт, а не перестановить произвольно.
Сложность
- Базовое решение: . Проходит подгруппу (36 баллов).
- Оптимизация до . Перебор пар + обновление симуляции при свапе — технически возможно, но требует аккуратной структуры (отслеживание «критических моментов» симуляции). Проходит (60 баллов).
- Полное решение: через префиксные минимумы и бинарный поиск. Полный балл.
Что ещё полезно потренировать
Задачи, где наблюдение про префиксный минимум / максимум решает задачу:
- Codeforces 1408A «Circle Coloring» — конструктивный анализ соседних элементов.
- Codeforces 1372C «Omkar and Baseball» — префиксы и суффиксы совпадения.
- Codeforces 1108D «Diverse Garland» — жадность с локальным анализом.
- Codeforces 1354E «Graph Coloring» — бинарный поиск по ответу в задаче на граф.
Общий мотив: «если заметить инвариант про префиксы — задача решается вместо ».
Итого
- Идея: в симуляции указатель двигается только у выигравшего;
simulate(a, b)за . - Решение на 36 баллов: перебор всех свапов .
- Полное решение (O(n log n)): префиксные минимумы руки + бинарный поиск — отдельная глубокая оптимизация, не раскрыта в этой статье.
- Ловушки: неверная модель указателей, попытка отсортировать всю руку, на .