← Вернуться в блог

Свапы как ориентация графа на значениях — задача «Два массива» РАЗБОР

  • 2200
  • constructive
  • graphs
  • dfs-bfs

Источник задачи: региональный этап Олимпиады им. М.В. Келдыша, 2025, задача F.

Что дано

Даны два массива a=(a1,,an)a = (a_1, \ldots, a_n) и b=(b1,,bn)b = (b_1, \ldots, b_n) одинаковой длины nn; все значения массивов — целые числа от 11 до 2n2n включительно. Разрешено выполнить произвольное число операций следующего вида: выбрать индекс i{1,,n}i \in \{1, \ldots, n\} и поменять местами значения aia_i и bib_i.

Обозначим f(c)f(c) — количество различных значений в массиве cc. Задача — максимизировать сумму f(a)+f(b)f(a) + f(b) после произвольного числа таких операций и выдать сами массивы aa и bb, на которых максимум достигается.

Ограничения

  • 1n1051 \leq n \leq 10^5
  • 1ai,bi2n1 \leq a_i, b_i \leq 2n

Формат ввода

Первая строка — одно число nn. Вторая строка — nn чисел a1,a2,,ana_1, a_2, \ldots, a_n через пробел. Третья строка — nn чисел b1,b2,,bnb_1, b_2, \ldots, b_n через пробел.

Формат вывода

Первая строка — одно число, максимальное значение f(a)+f(b)f(a) + f(b). Вторая строка — итоговый массив aa (через пробел). Третья строка — итоговый массив bb (через пробел).

Пример 1 руками

n = 5
a = [1, 2, 4, 4, 4]
b = [1, 3, 3, 5, 2]

Пары: (1,1),(2,3),(4,3),(4,5),(4,2)(1,1), (2,3), (4,3), (4,5), (4,2).

Операции — три свапа в позициях 2, 4 и 5:

После свапа i=2i=2: a2b2a_2 \leftrightarrow b_2a=[1,3,4,4,4]a = [1, 3, 4, 4, 4], b=[1,2,3,5,2]b = [1, 2, 3, 5, 2].

После свапа i=4i=4: a4b4a_4 \leftrightarrow b_4a=[1,3,4,5,4]a = [1, 3, 4, 5, 4], b=[1,2,3,4,2]b = [1, 2, 3, 4, 2].

После свапа i=5i=5: a5b5a_5 \leftrightarrow b_5a=[1,3,4,5,2]a = [1, 3, 4, 5, 2], b=[1,2,3,4,4]b = [1, 2, 3, 4, 4].

f(a)=5f(a) = 5 (все разные), f(b)=4f(b) = 4 (повторы: четвёрка). Сумма = 9. ✓


Идея решения

Граф на значениях

Построим граф на значениях, которые встречаются в массивах. Для каждого индекса ii добавим ребро между вершинами aia_i и bib_i (значения могут быть одинаковыми — тогда получаем петлю). Операцию свапа в позиции ii удобно интерпретировать как выбор ориентации этого ребра: если ii-е ребро ориентировано uvu \to v, то после всех операций ai=ua_i = u и bi=vb_i = v.

Задача: ориентировать все nn рёбер так, чтобы максимизировать число вершин, из которых исходит хотя бы одно ребро (вклад в f(a)f(a)), плюс число вершин, в которые входит хотя бы одно ребро (вклад в f(b)f(b)).

Переформулирование для ясности:

  • Вершины графа — различные значения в объединении aa и bb.
  • Рёбра — nn рёбер, по одному на каждый индекс ii.
  • Ориентация ребра {u,v}\{u, v\} как uvu \to v означает «после операций ai=u,bi=va_i = u, b_i = v».
  • f(a)={v:существует исходящее ребро из v}f(a) = |\{v : \text{существует исходящее ребро из } v\}| (вклад в aa).
  • f(b)={v:существует входящее ребро в v}f(b) = |\{v : \text{существует входящее ребро в } v\}| (вклад в bb).

Цель — ориентировать все рёбра так, чтобы максимизировать f(a)+f(b)f(a) + f(b) = «число вершин с исходящим» + «число вершин с входящим».

Вклад вершины

Для каждой вершины vv:

  • Если у vv есть и входящее, и исходящее ребро после ориентации — вклад 22.
  • Если только исходящее (или только входящее) — вклад 11.
  • Изолированная — вклад 00, но изолированных быть не может (каждая вершина появилась из-за хотя бы одного ребра).

Верхняя оценка: если deg(v)2\text{deg}(v) \geq 2, можно сделать и входящее, и исходящее — вклад 22. Если deg(v)=1\text{deg}(v) = 1 — только одно, вклад 11.

Но так ли просто? Нет: ориентация глобальна. Если у одной вершины хочется обе — какой-то соседний узел теряет.

Циклы и пути

Если каждое значение встречается 2\leq 2 раз (подгруппа 4), то граф — объединение путей и циклов (каждая вершина степени 2\leq 2).

  • Цикл. Ориентируем все рёбра «по часовой»: у каждой вершины ровно одно входящее и одно исходящее. Вклад каждой вершины — 22.
  • Путь v1v2vkv_1 - v_2 - \ldots - v_k. Ориентируем от начала к концу: v1v2vkv_1 \to v_2 \to \ldots \to v_k. У v1v_1 только исходящее (вклад 11), у vkv_k — только входящее (вклад 11), у внутренних по 22.

Это подгруппа 4 (15 баллов).

Общий случай

Если некоторые значения встречаются 3\geq 3 раз, граф имеет вершины степени 3\geq 3 — сложнее. Официальное решение делает так:

  1. Для каждого значения xx, встречающегося cntx\text{cnt}_x раз, создаём cntx/2\lceil \text{cnt}_x / 2 \rceil «клонов» этой вершины (это важный трюк).
  2. Получается граф, где у каждой вершины степень 2\leq 2 — то есть снова объединение путей и циклов.
  3. Применяем ориентацию по схеме «циклы полностью, путь от начала к концу».
  4. Ответ — сумма по всем значениям min(cntx,2)\min(\text{cnt}_x, 2).

Сложность: O(n)O(n).

Сложности вариантов

ВариантСложностьБаллы
Перебор 2n2^nO(2nn)O(2^n \cdot n)подгруппа 1 (n18n \leq 18) — 17 баллов
Подгруппы 2–5Аккуратные наблюдениядо 57 баллов накопленно
Полное решение через DFS-дерево или клонированиеO(n)O(n)100 баллов

В этой статье — код на 2n2^n (подгруппа 1) и идея полного решения.


Решение: псевдокод (для малых nn)

читать 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)

Работает для n18n \leq 18218184.71062^{18} \cdot 18 \approx 4.7 \cdot 10^6 операций.


Проверим на примерах

Пример 1

n=5n = 5, a=[1,2,4,4,4]a = [1, 2, 4, 4, 4], b=[1,3,3,5,2]b = [1, 3, 3, 5, 2].

Перебор маски 25=322^5 = 32. Лучшее — mask=0b10110\text{mask} = 0b10110: свапаем позиции 1, 2, 4 (0-based). A=[1,3,4,5,4]A = [1, 3, 4, 5, 4]... подожди, проверю: свап i=1i=1: (a1,b1)=(2,3)(3,2)(a_1, b_1) = (2, 3) \to (3, 2). Свап i=2i=2: (4,3)(3,4)(4, 3) \to (3, 4). Свап i=4i=4: (4,2)(2,4)(4, 2) \to (2, 4).

После: A=[1,3,3,4,2]A = [1, 3, 3, 4, 2], B=[1,2,4,5,4]B = [1, 2, 4, 5, 4]. set(A)=1,3,4,2=4|set(A)| = |{1,3,4,2}| = 4, set(B)=1,2,4,5=4|set(B)| = |{1,2,4,5}| = 4. Сумма 8.

Нужно другое: A=[1,3,4,5,2],B=[1,2,3,4,4]A = [1, 3, 4, 5, 2], B = [1, 2, 3, 4, 4] → сумма 9. Это маска {1,3,4}\{1, 3, 4\}: позиции 1, 3, 4. Mask = 0b11010=260b11010 = 26.

Проверим: mask=26, биты 1, 3, 4 (0-indexed). Свап i=1i=1: (2,3)(3,2)(2, 3) \to (3, 2). Свап i=3i=3: (4,5)(5,4)(4, 5) \to (5, 4). Свап i=4i=4: (4,2)(2,4)(4, 2) \to (2, 4).

A=[1,3,4,5,2]A = [1, 3, 4, 5, 2], B=[1,2,3,4,4]B = [1, 2, 3, 4, 4]. f(A)=5f(A) = 5, f(B)=4f(B) = 4. Сумма 9. ✓

Пример 2

n=7n = 7, a=[2,2,4,4,5,5,5]a = [2, 2, 4, 4, 5, 5, 5], b=[1,3,3,2,1,6,6]b = [1, 3, 3, 2, 1, 6, 6]. Ожидается 12.

f(a)+f(b)=6+6=12f(a') + f(b') = 6 + 6 = 12. Перебор 27=1282^7 = 128 вариантов — подтверждает.

Пример 3

n=7n = 7, a=[12,3,3,4,5,6,4]a = [12, 3, 3, 4, 5, 6, 4], b=[1,2,13,8,10,13,7]b = [1, 2, 13, 8, 10, 13, 7]. Ожидается 14.

Тоже проверяется перебором.


Крайние случаи

  1. Все значения различны. f(a)+f(b)=2nf(a) + f(b) = 2n. Свапы не меняют.

  2. Все одинаковые. a=b=[k,k,,k]a = b = [k, k, \ldots, k]. f(a)=f(b)=1f(a) = f(b) = 1. Свапы не помогают. Сумма 22.

  3. n=1n = 1. Пара (a1,b1)(a_1, b_1). Если a1=b1a_1 = b_1 — сумма 22 (каждый массив 1 элемент). Иначе — тоже 22 (один в aa, один в bb, оба различные). Свап ничего не меняет (только две одинаковые конфигурации).

  4. Большие nn (до 10510^5). Перебор 2n2^n не пройдёт. Нужно полное решение через граф — см. идею выше.


Типичные ошибки

  1. Попытка жадно свапать по одному. Жадность «если свап увеличит сумму — свапаем» даёт локальный оптимум, но не глобальный. Контрпример — любой цикл из 3 ребер: локально поменять ориентацию одного ребра не улучшит, но глобальная переориентация всего цикла в одну сторону улучшает.

  2. Забыть, что вершина с одним ребром приносит вклад ≤ 1. Не 2. Если увидеть это только в конце — переделывать задачу придётся с нуля.

  3. Не учесть одинаковые элементы ai=bia_i = b_i. Такое ребро = петля в графе. В ориентированном графе петля vvv \to v даёт vv и входящее, и исходящее — вклад 22. Но значение входит в aa и bb один раз — и в сумме считаем 22. Никаких особых проблем, но удобно замечать.

  4. Перебор 2n2^n для n>20n > 20. Забыть, что такой алгоритм не проходит полный тест.


Сложность

  • Перебор: O(2nn)O(2^n \cdot n). Подгруппа 1 (n18n \leq 18), 17 баллов.
  • Полное решение: O(n)O(n) через разложение графа на циклы и пути с «клонированием» значений высокой частоты.

Что ещё полезно потренировать

Задачи на ориентацию графов и разложение на циклы/пути:

  • Codeforces 508D «Tanya and Password» — восстановление эйлерова пути.
  • Codeforces 723E «One-Way Reform» — ориентация рёбер для эйлерова цикла.
  • Codeforces 547D «Mike and Fish» — ориентация на двудольном графе, симметричная задача.
  • Codeforces 1178F2 «Long Colorful Strip (Hard)» — сложная DP, но с характерным разложением на сегменты.

Общий мотив: «задача превращается в граф, и требуется умная ориентация или разложение на элементарные объекты (пути, циклы)».


Итого

  • Сведение: пара индексов (ai,bi)(a_i, b_i) — ребро графа между значениями; свап = выбор ориентации.
  • Цель: максимизировать сумму «вершин с исходящим» и «вершин с входящим» — для вершины степени 2\geq 2 вклад 22, для листа 11.
  • Простое решение: перебор 2n2^n масок, O(2nn)O(2^n \cdot n). Подгруппа 1.
  • Полное решение: разложение графа на циклы и пути (с предварительным клонированием вершин высокой степени), ориентация каждого компонента отдельно. O(n)O(n).
  • Ловушки: локальная жадность не работает; забыть про вклад 11 для листьев; ai=bia_i = b_i — это петля.

Попробуй разобрать похожие задачи

В CodePal AI-партнёр подсказывает идею, а не ответ. Разбор в диалоге, код проверяется в браузере.