Разбор задач Educational Codeforces Round 3

Revision ru1, by Edvard, 2015-12-19 17:50:23

600A - Выделение чисел

Эта задача является чисто технической. Нужно было сделать ровно то, что написано в условии.

600B - Запросы о количестве не превосходящих элементов

Давайте отсортируем числа первого массива. Теперь будем идти по второму массиву и для текущего числа bj найдем бинарным поиском индекс первого большего числа в первом массива. Этот индекс и будет являться ответом.

Другим подходом в этой задаче было следующее: отсортируем оба массива сохранив при этом индексы чисел (например можно сортировать пары <значение, позиция>). Теперь будем идти по второму массиву и хранить переменную p — указатель на первый элемент ap такой, что он больше текущего bj. Поскольку оба массива отсортированы указатель можно не сбрасывать на каждой итерации, а просто двигать его дальше вправо.

Асимптотическая сложность решения: O(nlogn).

600C - Сделай палиндром

Давайте посчитаем для каждого символа c сколько раз он встречается в s. Обозначим эту величину cntc. Рассмотрим нечетные cntc. В палиндроме нечетных cntc может быть не больше одного. Пусть a1, a2...ak — это символы с нечетным cntc в алфавитном порядке. Заменим любой символ ak символом a1, символ ak - 1 символом a2 и так далее пока не дойдем середины. Теперь у нас имеется имеется не более одного нечетного символа. Если нечетный символ есть поставим его в середину ответа. А в первую половину возьмем от всех букв cntc / 2 в алфавитном порядке. Например, если s = aabcd мы сначала заменим d на b, после этого поставим символ c в середину и после перестановки остальных символов получим строку abcba.

Асимптотическая сложность решения: O(n).

600D - Площадь пересечения двух кругов

Давайте сразу отбросим случай когда круги не пересекаются, в это случае ответ равен 0. Это можно проверить в целых числах, сравнив квадрат расстояния между центра с квадратом суммы радиусов. Также отбросим случай, когда один круг полностью лежит внутри другого, в этом случае ответ есть площадь маленького круга. Это тоже можно проверить в целых числах, сравнив квадрат расстояния между центра с квадратом разности радиусов. Отлично теперь можно рассмотреть общий случай. Ответ будет складываться из некоторого сегмента первого круга и некоторого сегмента второго круга. Для того, чтобы определить угол первого сегмента рассмотрим треугольник, образованный центрами кругов и одной из точек пересечения. В этом треугольнике мы знаем все три стороны, значит по теореме косинусов может определить угол сегмента. Значит мы можем определить площадь сектора. Теперь остается вычесть из этого площадь треугольника образованного одним из центров и точками пересечения кругов. А это можно сделать, посчитав площадь как половина модуля псевдовекторного произведения. Таким образом получаются следующие формулы: ,

где d — расстояние между центрами. И соответственно тоже самое нужно сделать для первого круга, поменяв индексы 1 ≤ ftrightarrow2.

Асимптотическая сложность решения: O(1).

600E - Lomsat gelral

Название этой задачи является анаграммой к Small to large. И это не спроста :-) Авторское решение по этой задаче использует классическую технику пересчета множеств на дереве. Простейшим решением этой задачи является следующее: давайте для каждой вершины поддерживать один map<int, int> — для каждого цвета, сколько раз он встречается, один set<pair<int, int>> — пары количество повторений и цвет, и число sum являющееся суммой самых частых символов. Для того, чтобы посчитать эти величины для вершины v нужно сначала посчитать их для всех сыновей, а потом просто сливать эти значения. Такой подход правильный, но медленный (сложность получится O(n2logn)). Но давайте немного улучшим это решение, каждый раз когда нам надо склеить 2 mapa и b, будем клеить меньший из них (просто итерируясь по нему) к большему (это и есть small to large). Давайте теперь рассмотрим цвет какой-нибудь вершины: каждый раз, когда он будет перекидываться из одного map-а в другой размер другого будет как минимум вдвое больше. Таким образом, это цвет поперебрасывается не более logn раз. Каждой перебрасывание делается за O(logn). Просуммировав это по всем вершинам получаем сложность O(nlog2n).

Также стоит заметить, что у некоторых участников было другое решение, но эта техника является общей и применяется в широком круге задач.

600F - Раскраска ребер двудольного графа

Введем обозначение d — наибольшая из степеней вершин в графе. Утверждение: ответ равен d. Докажем это утверждение, построив конструктивный алгоритм (он и будет решением задачи). Давайте красить ребра по очереди в любом порядке. Пусть текущее ребро (x, y). Если сейчас существует цвет c, который свободен и в вершине x и в вершине y, мы просто красим ребро в цвет c. Если такого цвета нет обязательно существует пара цветов c1, c2 такая, что c1 есть в x но нет в y, а цвет c2 есть в y но нет в x. Давайте освободим вершину y от цвета c2. Рассмотрим другой конец ребра исходящего из вершины y цвета c2. Пусть это вершина z. Если у вершины z цвет c1 свободен мы можем покрасить ребра x, y в цвет c2, а ребро y, z перекрасить в цвет c1. Таким образом мы проведем чередование. Если же у вершины z цвет c1 занят посмотрим на следующую вершину по цвету — w. Если это вершина не содержит ребра цвета c2 мы снова можем провести чередование. И так далее. Поскольку граф двудольный мы обязательно сможем найти чередующуюся цепочку. Поиск цепочки можно сделать обходом в глубину. Длина цепочки порядка O(n). Поэтому окончательно имеем:

Сложность решения: O(nm).

Tags educational round 3, editorial

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en7 English Edvard 2015-12-20 03:58:40 33
ru9 Russian Edvard 2015-12-20 03:57:21 32
en6 English Edvard 2015-12-20 03:54:38 1619
en5 English Edvard 2015-12-20 03:41:51 2 Tiny change: 'e it is:\nSome spa' -> 'e it is:\n\nSome spa'
en4 English Edvard 2015-12-20 03:41:23 345
ru8 Russian Edvard 2015-12-20 03:39:45 9 Мелкая правка: 'ер метода lower_bound в C++). В' -> 'ер метода \texttt{lower_bound} в C++). В'
en3 English Edvard 2015-12-20 03:22:44 1225
en2 English Edvard 2015-12-20 01:45:23 1503
ru7 Russian Edvard 2015-12-20 01:23:37 8
ru6 Russian Edvard 2015-12-20 01:21:21 2 Мелкая правка: 'ведем функицю $f(d)$, ' -> 'ведем функцию $f(d)$, '
ru5 Russian Edvard 2015-12-20 01:19:46 2 Мелкая правка: 'Пусть $lf=1$ &mdash; ' -> 'Пусть $lf=0$ &mdash; '
en1 English Edvard 2015-12-20 01:07:43 1959 Initial revision for English translation
ru4 Russian Edvard 2015-12-19 22:47:25 40 Мелкая правка: ' + m))$.\n' -> ' + m))$.\n\n[Code](http://pastebin.com/MTWxiD1s)\n'
ru3 Russian Edvard 2015-12-19 22:20:38 1049 Мелкая правка: ' $O(n log^2n)$. Но эт' -
ru2 Russian Edvard 2015-12-19 20:08:22 12575 Мелкая правка: 'шения: $O(k logn)$.\n\n[pr' - (опубликовано)
ru1 Russian Edvard 2015-12-19 17:50:23 5836 Первая редакция (сохранено в черновиках)