Источник задачи: региональный этап Олимпиады им. М.В. Келдыша, 2025, задача F.
Что дано
Даны два массива и одинаковой длины ; все значения массивов — целые числа от до включительно. Разрешено выполнить произвольное число операций следующего вида: выбрать индекс и поменять местами значения и .
Обозначим — количество различных значений в массиве . Задача — максимизировать сумму после произвольного числа таких операций и выдать сами массивы и , на которых максимум достигается.
Ограничения
Формат ввода
Первая строка — одно число . Вторая строка — чисел через пробел. Третья строка — чисел через пробел.
Формат вывода
Первая строка — одно число, максимальное значение . Вторая строка — итоговый массив (через пробел). Третья строка — итоговый массив (через пробел).
Пример 1 руками
n = 5
a = [1, 2, 4, 4, 4]
b = [1, 3, 3, 5, 2]
Пары: .
Операции — три свапа в позициях 2, 4 и 5:
После свапа : → , .
После свапа : → , .
После свапа : → , .
(все разные), (повторы: четвёрка). Сумма = 9. ✓
Идея решения
Граф на значениях
Построим граф на значениях, которые встречаются в массивах. Для каждого индекса добавим ребро между вершинами и (значения могут быть одинаковыми — тогда получаем петлю). Операцию свапа в позиции удобно интерпретировать как выбор ориентации этого ребра: если -е ребро ориентировано , то после всех операций и .
Задача: ориентировать все рёбер так, чтобы максимизировать число вершин, из которых исходит хотя бы одно ребро (вклад в ), плюс число вершин, в которые входит хотя бы одно ребро (вклад в ).
Переформулирование для ясности:
- Вершины графа — различные значения в объединении и .
- Рёбра — рёбер, по одному на каждый индекс .
- Ориентация ребра как означает «после операций ».
- (вклад в ).
- (вклад в ).
Цель — ориентировать все рёбра так, чтобы максимизировать = «число вершин с исходящим» + «число вершин с входящим».
Вклад вершины
Для каждой вершины :
- Если у есть и входящее, и исходящее ребро после ориентации — вклад .
- Если только исходящее (или только входящее) — вклад .
- Изолированная — вклад , но изолированных быть не может (каждая вершина появилась из-за хотя бы одного ребра).
Верхняя оценка: если , можно сделать и входящее, и исходящее — вклад . Если — только одно, вклад .
Но так ли просто? Нет: ориентация глобальна. Если у одной вершины хочется обе — какой-то соседний узел теряет.
Циклы и пути
Если каждое значение встречается раз (подгруппа 4), то граф — объединение путей и циклов (каждая вершина степени ).
- Цикл. Ориентируем все рёбра «по часовой»: у каждой вершины ровно одно входящее и одно исходящее. Вклад каждой вершины — .
- Путь . Ориентируем от начала к концу: . У только исходящее (вклад ), у — только входящее (вклад ), у внутренних по .
Это подгруппа 4 (15 баллов).
Общий случай
Если некоторые значения встречаются раз, граф имеет вершины степени — сложнее. Официальное решение делает так:
- Для каждого значения , встречающегося раз, создаём «клонов» этой вершины (это важный трюк).
- Получается граф, где у каждой вершины степень — то есть снова объединение путей и циклов.
- Применяем ориентацию по схеме «циклы полностью, путь от начала к концу».
- Ответ — сумма по всем значениям .
Сложность: .
Сложности вариантов
| Вариант | Сложность | Баллы |
|---|---|---|
| Перебор | подгруппа 1 () — 17 баллов | |
| Подгруппы 2–5 | Аккуратные наблюдения | до 57 баллов накопленно |
| Полное решение через DFS-дерево или клонирование | 100 баллов |
В этой статье — код на (подгруппа 1) и идея полного решения.
Решение: псевдокод (для малых )
читать n, a[], b[]
ответ = 0
для mask = 0..(2^n - 1):
строим A, B из (a, b) с применением свапа для битов маски
cur = f(A) + f(B)
если cur > ответ:
ответ = cur
save A, B
вывести ответ, A, B
Код решения (подгруппа 1)
Работает для — операций.
Проверим на примерах
Пример 1
, , .
Перебор маски . Лучшее — : свапаем позиции 1, 2, 4 (0-based). ... подожди, проверю: свап : . Свап : . Свап : .
После: , . , . Сумма 8.
Нужно другое: → сумма 9. Это маска : позиции 1, 3, 4. Mask = .
Проверим: mask=26, биты 1, 3, 4 (0-indexed). Свап : . Свап : . Свап : .
, . , . Сумма 9. ✓
Пример 2
, , . Ожидается 12.
. Перебор вариантов — подтверждает.
Пример 3
, , . Ожидается 14.
Тоже проверяется перебором.
Крайние случаи
-
Все значения различны. . Свапы не меняют.
-
Все одинаковые. . . Свапы не помогают. Сумма .
-
. Пара . Если — сумма (каждый массив 1 элемент). Иначе — тоже (один в , один в , оба различные). Свап ничего не меняет (только две одинаковые конфигурации).
-
Большие (до ). Перебор не пройдёт. Нужно полное решение через граф — см. идею выше.
Типичные ошибки
-
Попытка жадно свапать по одному. Жадность «если свап увеличит сумму — свапаем» даёт локальный оптимум, но не глобальный. Контрпример — любой цикл из 3 ребер: локально поменять ориентацию одного ребра не улучшит, но глобальная переориентация всего цикла в одну сторону улучшает.
-
Забыть, что вершина с одним ребром приносит вклад ≤ 1. Не 2. Если увидеть это только в конце — переделывать задачу придётся с нуля.
-
Не учесть одинаковые элементы . Такое ребро = петля в графе. В ориентированном графе петля даёт и входящее, и исходящее — вклад . Но значение входит в и один раз — и в сумме считаем . Никаких особых проблем, но удобно замечать.
-
Перебор для . Забыть, что такой алгоритм не проходит полный тест.
Сложность
- Перебор: . Подгруппа 1 (), 17 баллов.
- Полное решение: через разложение графа на циклы и пути с «клонированием» значений высокой частоты.
Что ещё полезно потренировать
Задачи на ориентацию графов и разложение на циклы/пути:
- Codeforces 508D «Tanya and Password» — восстановление эйлерова пути.
- Codeforces 723E «One-Way Reform» — ориентация рёбер для эйлерова цикла.
- Codeforces 547D «Mike and Fish» — ориентация на двудольном графе, симметричная задача.
- Codeforces 1178F2 «Long Colorful Strip (Hard)» — сложная DP, но с характерным разложением на сегменты.
Общий мотив: «задача превращается в граф, и требуется умная ориентация или разложение на элементарные объекты (пути, циклы)».
Итого
- Сведение: пара индексов — ребро графа между значениями; свап = выбор ориентации.
- Цель: максимизировать сумму «вершин с исходящим» и «вершин с входящим» — для вершины степени вклад , для листа .
- Простое решение: перебор масок, . Подгруппа 1.
- Полное решение: разложение графа на циклы и пути (с предварительным клонированием вершин высокой степени), ориентация каждого компонента отдельно. .
- Ловушки: локальная жадность не работает; забыть про вклад для листьев; — это петля.