Пошаговый разбор для новичков. Educational Codeforces Round 191 (Rated for Div. 2)
Difference between ru12 and ru13, changed 0 character(s)
Всем Привет!↵

![ ](/predownloaded/92/d1/92d185b9a970affe38f3d3b1f1660b5a3a7e8055.png)↵

Меня зовут Максим и я очень давно хочу достичь рейтинга 3000. Я верю, что для этого мне надо научиться мыслить, как человек, у которого уже есть 3000 рейтинга. Очень часто в разборах пишут фразы "заметим, что..." или "докажем вот такой факт..." и дальше идет долгое доказательство этого факта. А то, каким образом я должен к этому факту прийти, как эта мысль должна зародиться у меня в голове, никто нигде не пишет. Я думаю, что не только у меня есть эта проблема, поэтому вместо того, чтобы ждать понятный разбор, я решил начать с себя. Именно поэтому, я решил написать пошаговый разбор, где я буду описывать ход своих мыслей и действий, которые позволяют мне придумать эти самые идеи.↵

Также, я создал группу по прокачке навыков спортивного программирования для людей с рейтингом 1200- , чтобы помочь им стать лучше и достигнуть рейтинга 1500+. Если хотите больше об этом узнать, рекомендую прочитать [ЭТОТ ПОСТ](https://codeforces.me/blog/entry/153213) или заполнить [ФОРМУ](https://forms.yandex.ru/u/69ea4ba0493639794fd019d8). Эту группу я назвал **Polaris** в честь путеводной звезды. В Polaris ребята решают специально подобранные контесты под их уровень, дорешивают их с помощью пошаговых разборов, изучают новую теорию, решают специально подготовленные для них подводящие упражнения, а также получают подробные рекомендации на основе их участия в тренировочных контестах. Более того, специально для участников группы я делаю пошаговые разборы тех задач, которые интересны самим участникам. Также, в группе регулярно ведется обсуждение прошедших контестов, а в ближайшем будущем мы будем готовиться к предстоящим олимпиадам (как школьным, так и студенческим). Присоединяйтесь, я буду вам очень рад!↵

А теперь перейдем к самому разбору контеста. Но перед этим, я бы хотел ввести несколько правил чтения разбора для того, чтобы вы смогли получить максимум пользы от него.↵

1. Перед чтением разбора задачи, убедитесь, что вы прочитали задачу, подумали над ней, извлекли из своей головы и записали/нарисовали максимальное количество идей и больше уже ничего не можете придумать.↵
2. Во время чтения разбора, если в какой-то момент, какое-то предложение в разборе навело вас на новую мысль, перестаньте читать разбор и вернитесь к пункту (1), а именно продолжите с этого места генерировать новые идеи. Это очень важно.↵
3. Если вы дочитали текст разбора до конца и не поняли, как решать задачу или остались вопросы, то их нужно обязательно задать в комментариях или спросить в Polaris. Там вам помогут я и ребята, кто справился с этой задачей. Также в этом случае, полезно прочитать код, который будет прикреплен к разбору.↵
4. После того, как вы решили задачу, обязательно посмотрите код других участников и код с разбора. Возможно, он наведет вас на мысль о том, как можно было проще и быстрее реализовать решение задачи.↵

A. Разработка ИИ-проекта↵
===================↵

<spoiler summary="Шаг 1">↵
Судя по всему, нужно аккуратно расписать формулы в соответствии с условием задачи. Предположим, что мы знаем, что ответ равен $T$. Какие на него есть условия, когда Никита не использует ИИ? Сколько строк кода напишут ребята?↵
</spoiler>↵

<spoiler summary="Шаг 2">↵
Они напишут $T\cdot (x + y)$ строк кода и мы хотим, чтобы выполялось $T\cdot (x + y) \ge n$, тогда $T \ge \frac{n}{x+y}$. А что если они будут использовать ИИ?↵
</spoiler>↵

<spoiler summary="Шаг 3">↵
Тогда они напишут $T\cdot x + (T-z)\cdot 10\cdot y$ строк. Какое тогда есть ограничение на $T$?↵
</spoiler>↵

<spoiler summary="Шаг 4">↵
$T\cdot x + (T-z)\cdot 10\cdot y \ge n$, тогда $T\cdot(x+10y) \ge n + 10zy$, тогда $T \ge \frac{n + 10zy}{x+10y}$. ↵
</spoiler>↵

<spoiler summary="Шаг 5">↵
Выбираем максимум из двух выражений и округляем вверх.↵
</spoiler>↵

Решение: [submission:377920759]↵


B. Различные расстояния↵
===================↵

<spoiler summary="Шаг 1">↵
Какой самый простой случай можно рассмотреть?↵
</spoiler>↵

<spoiler summary="Шаг 2">↵
Когда $n=2$. Как его решить?↵
</spoiler>↵

<spoiler summary="Шаг 3">↵
Обозначим два числа за $X,Y$, тогда можно взять например такой ответ: "XYYXXYXY", тогда для $X$ расстояния образуют множество $(3,1,2)$, а у $Y$ множество $(1,3,2)$. Как теперь решить для случая $n=3$?↵
</spoiler>↵

<spoiler summary="Шаг 4">↵
Можно например взять ответ из прмеров или например такую строку: "XYZXXZXYYZZY". Как теперь решить задачу для четных $n$?↵
</spoiler>↵

<spoiler summary="Шаг 5">↵
Можно разбить числа на пары $(1,2),(3,4),\ldots,(n-1,n)$, для каждой пары мы можем построить блок длины $8$, останется их только склеить. А как решить задачу для нечетных $n$?↵
</spoiler>↵

<spoiler summary="Шаг 6">↵
Если $n$ нечетное, то $n \ge 3$, тогда мы можем построить блок для чисел $(n-2,n-1,n)$ длины $12$. Нам остается только решить задачу для оставшихся $(n-3)$ чисел. А это мы уже умеем делать, т.к. $(n-3)$ &mdash; четное число.↵
</spoiler>↵

Решение: [submission:377932509]↵

C. Стоимость скобочной последовательности↵
===================↵

<spoiler summary="Шаг 1">↵
Первое, на что обратил внимание &mdash; это ограничения задачи, которые позволяют ее решить за $O(n^2)$, то есть можно что-нибудь перебрать за $O(n)$, а дальше посчитать что-то за $O(n)$.↵
</spoiler>↵

<spoiler summary="Шаг 2">↵
У нас есть скобки всего двух типов: "(" и ")". Пусть мы удалим $x$ скобок "(" и $y$ скобок ")", тогда $x+y \le k$. Какие скобки типа "(" нам выгоднее всего удалять?↵
</spoiler>↵

<spoiler summary="Шаг 3">↵
Нам выгоднее всего удалить $x$ самых левых скобок "(", почему?↵
</spoiler>↵

<spoiler summary="Шаг 4">↵
Посмторим на оптимальный ответ. В нем мы можем найти ПСП какой-то длины. Посмотрим на первый символ этой ПСП, он равен "(", причем мы можем считать, что это самая первая скобка в строке (если это не так, тогда мы можем заменить первый символ на скобку "(" левее). Т.к. мы предположили, что мы удалили не $x$ самых левых скобок "(", тогда есть удаленная скобка, которая правее скобки "(" в ПСП, мы можем вместо удаления этой более правой скобки удалить скобку из ПСП, тогда сама ПСП не увеличится.↵

Хорошо, а какие тогда скобки ")" нам выгоднее всего удалять?↵
</spoiler>↵

<spoiler summary="Шаг 5">↵
Нам выгоднее всего удалять $y$ самых правых скобок ")". Как тогда решать задачу? Что можно перебрать?↵
</spoiler>↵

<spoiler summary="Шаг 6">↵
Мы можем перебрать $x$ за $O(n)$, тогда $y=k-x$. Остается только удалить скобки за $O(n)$ и посчитать длину максимальной ПСП в оставшейся строке. Как это сделать?↵
</spoiler>↵

<spoiler summary="Шаг 7">↵
Можно это сделать жадно. Будем идти слева направо и поддерживать текущее количество скобок "(" без парной ")" (пусть это число равно $b$), а также количество уже спаренных скобок (это и есть длина ПСП). Если текущий символ "(", что тогда можем сделать?↵
</spoiler>↵

<spoiler summary="Шаг 8">↵
Можем увеличить $b$ на единицу, а если текущий символ &mdash; это ")"?↵
</spoiler>↵

<spoiler summary="Шаг 9">↵
Тогда мы можем попытаться спарить эту скобку с какой-то из "(". То есть, если $b > 0$, то мы можем уменьшить $b$ на единицу и увеличить ответ на $2$.↵
</spoiler>↵

Решение: [submission:377946709]↵

D. Товары на полке↵
===================↵

<spoiler summary="Шаг 1">↵
Первое, на что обратил внимание, что мы можем сжать координаты и считать, что $0 \le a_i < n$. Тогда для каждого $0 \le x < n$ мы можем выписать все позиции $i$, что $a_i=x$.↵
</spoiler>↵

<spoiler summary="Шаг 2">↵
Как нам для конкретного $x$ проверить, что все числа в массиве $a_i=x$ образуют один отрезок?↵
</spoiler>↵

<spoiler summary="Шаг 3">↵
Пусть $l$ &mdash; минимальная позиция $a_l=x$, а $r$ &mdash; максимльная, пусть $c$ &mdash; количество элементов в массиве, равных $x$. Как проверить условие?↵
</spoiler>↵

<spoiler summary="Шаг 4">↵
Достаточно проверить, что $r - l + 1 = c$. Хорошо, теперь какой бывает простой случай?↵
</spoiler>↵

<spoiler summary="Шаг 5">↵
Пусть $F(x) = 1$, если $x$ образует единый отрезок и $0$ иначе. Тогда простой случай, когда $F(x)=1$ для всех $x$. Хорошо, осталося случай, когда есть какой-то $y$, что $F(y)=0$. Что тогда? Какую позицию тогда точно нужно будет поменять?↵
</spoiler>↵

<spoiler summary="Шаг 6">↵
Тогда мы знаем, что $r-l+1 > c$ и есть "дырки", то есть позиции, в которых стоят какие-то другие числа. В таком случае мы будем обязаны обменять местами либо $l$, либо $r$ с кем-то другим, т.к. иначе величина $r-l+1$ может только увеличиться, а $c$ не изменится. Тогда сколько всего можно перебрать пар для обмена местами?↵
</spoiler>↵

<spoiler summary="Шаг 7">↵
Мы можем перебрать пары $(l,i),(r,i)$ для всех $i$, то есть всего есть $O(n)$ пар. Как нам для конкретной пары проверить, помогает ли она или нет?↵
</spoiler>↵

<spoiler summary="Шаг 8">↵
Мы можем поддерживать множество позиций в `std::set<int>`, тогда операцию `swap` и проверку конкретного $x$ можно еализовать за $O(\log{n})$. Как тогда решить задачу?↵
</spoiler>↵

<spoiler summary="Шаг 9">↵
Давайте поддерживать количество $x$, что $F(x)=0$↵
Давайте переберем все пары для `swap` , сделаем этот `swap` и обновим количество плохих $x$-ов. Если помогло, то выводим ответ, а иначе меняем обратно, возвращая все на место и идем дальше.↵
</spoiler>↵

Решение: [submission:377946709]↵

E1. Передача перестановки (простая версия)↵
===================↵

<spoiler summary="Шаг 1">↵
Зафиксирую конкетную перестановку бит из условия. Какие простые условия можно проверить?↵
</spoiler>↵

<spoiler summary="Шаг 2">↵
Мы хотим, чтобы не было нуля, а также чтобы все числа были разные. Тогда какое единственное условие может быть нарушено?↵
</spoiler>↵

<spoiler summary="Шаг 3">↵
Скажем, что перестановка бит хорошая, если максимальный элемент после перестановки бит не больше $n$. Тогда чему равен ответ?↵
</spoiler>↵

<spoiler summary="Шаг 4">↵
Он равен количеству хороших перестановок, потому что разные перестановки бит дают разные перестановки массива $p$. Можем ли мы перебрать все перестановки бит $a_0,a_1,\ldots,a_{k-1}$?↵
</spoiler>↵

<spoiler summary="Шаг 5">↵
Да, можем, потому что $\log_2(n) \le 11$, а $11! \le 4\cdot 10^7$. Что останется сделать?↵
</spoiler>↵

<spoiler summary="Шаг 6">↵
Останется проверить, что для конкретной перестановки бит все числа будут не больше $n$. Что значит, что число $x$ больше числа $n$?↵
</spoiler>↵

<spoiler summary="Шаг 7">↵
Это когда мы сравниваем два числа начиная со старших бит и находим первое несовпадение в бите $j$ и так оказывается, что $n_j=0,x_j=1$, то есть $j$-й бит числа $n$ равен нулю, а у числа $x$ он равен единице.↵
</spoiler>↵

<spoiler summary="Шаг 8">↵
Тогда мы можем перебирать биты начиная со старшего, пусть смотрим на бит $j$, тогда мы хотим проверить, есть ли число $x$, что в битах $a_q$ (здесь $q > j$) в нем стоит то же самое, что в бите $q$ числа $n$, а в бите $a_q$ стоит единица, в то время как у $n$ стоит ноль. Как мы можем это проверить?↵
</spoiler>↵

<spoiler summary="Шаг 9">↵
Перебирая биты мы можем поддерживать маску бит, которые нам интересны, а также строить желаемое число которое мы хотим получить. Дальше мы можем запомнить для каждой маски, какие есть числа в исходном массиве, если мы хотим рассматривать только биты из конкретной маски.↵
</spoiler>↵

Решение: [submission:377975138]

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
ru13 Russian specia1 2026-06-10 17:52:11 0 (опубликовано)
ru12 Russian specia1 2026-06-10 17:51:15 654
ru11 Russian specia1 2026-06-10 17:48:21 625
ru10 Russian specia1 2026-06-10 17:45:59 576
ru9 Russian specia1 2026-06-10 17:43:19 145
ru8 Russian specia1 2026-06-10 17:28:59 2087
ru7 Russian specia1 2026-06-10 17:19:55 2144
ru6 Russian specia1 2026-06-10 17:09:43 1218
ru5 Russian specia1 2026-06-10 17:04:21 2 Мелкая правка: 'ac{n + 10z}{x+10zy}$. \n</s' -> 'ac{n + 10zy}{x+10y}$. \n</s'
ru4 Russian specia1 2026-06-10 17:03:19 2
ru3 Russian specia1 2026-06-10 17:02:22 13681
ru2 Russian specia1 2026-06-10 16:56:35 12 Мелкая правка: ' написать свой первый пошаговый' -> ' написать пошаговый'
ru1 Russian specia1 2026-06-10 16:55:54 15884 Первая редакция (сохранено в черновиках)