# Разбор задач 2021 года Если Вы не знали, как решать какую-то задачу, и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас. :::warning Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя! ::: ## [1. Покупка подарков](https://codeforces.com/group/skz9fIV5Hq/contest/351464/problem/A) :::spoiler Разбор :::info Аккуратно напишем, что просят в условии задачи. Нужно не забыть учесть выход за границы линии из коробок. Пример алгоритма: Из первого пройдем вправо, потом обратно. Поставим одну коробку. Будем повторять, пока не все коробки лежат на первом месте. В других случаях будем ходить влево, а потом назад. Не забудьте про случаи, когда n = 1 ::: ## [2. Первое имя](https://codeforces.com/group/skz9fIV5Hq/contest/351464/problem/B) :::spoiler Разбор :::info Одна из самых интересных задач соревнования. Давайте поймем, какую строку следует приписать на текущей иттерации. Если осталось одна строка, то очевидным образом можно выполнить действие. Если есть 2 и более строки: Тогда из двух строк $a$ и $b$ будет идти раньше: $a$, если $a + b$ < $b + a$ $b$, иначе. Теперь можно отсортировать слова. В чем логика? Очевидно, что итоговое слово должно начинатся на минимальную букву. Что делать, если таких слов несколько? Какую из двух строк выгоднее поставить первой. Ту, которая при соеденении(a + b, b + a) дает меньшую(лексикографически) строку. Тогда можно найти минимальную строку, которую следует поставить на первую позицию. Для остальных позиций аналогично. Как реализовать? Можно написать компоратор для сортировки $O(n*log(n))$. Есть константа длины строк 50, т.е. $O(n*log(n)*50)$. Можно написать спуск по бору $O(n)$. Есть константа 26(количество букв) и длины строк 50, т.е. $O(n*26*50)$. Из практики, оба решения работают одиннаково по времени(очевидно, быстрее написать сортировку). ::: ## [3. Навигация](https://codeforces.com/group/skz9fIV5Hq/contest/351464/problem/C) :::spoiler Разбор :::info Основная идея в том, чтобы перебирать момент времени, после которого корабль сможет доплыть до финиша. Это можно сделать, т.к. смещение корабля ветром и его движение суммируются. Давайте промоделируем первые $i$ дней. Тогда, чтобы можно было добраться до финиша достаточно условия $abs(tech.x - fin.x) + abs(tech.y - fin.y) \leq i$. ::: ## [4. Украшение ландшафта](https://codeforces.com/group/skz9fIV5Hq/contest/351464/problem/D) :::spoiler Разбор :::info [BaluconisTima](https://codeforces.com/profile/BaluconisTima) Давайте использовать бинарный поиск по ответу. Значит, теперь нам надо теперь решить следующую задачу: У нас есть n чисел. Нам надо изменить максимум m из них так, чтобы разница между числами была не более mid. Эта задача решается методом динамического программирования, где dp[i] - сколько чисел можно не изменять до i так, чтобы выполнялось нужное нам свойство. переходы достаточно просты: Мы знаем точный ответ для dp[i]. Попробуем найти с помощью него ответ для dp[j], где j > i. Представим, что мы изменим все между ними. В таком случае, мы можем сделать переход, если abs(a[i] - a[j]) <= mid * (j - i), тогда dp[j] = max(dp[j], dp[i] + 1); К примеру, mid = 2, i = 1, j = 4. 1 500 135 2143 9 В таком случае заменим числа между ними подобным образом: 1 3 5 7 9 То есть, если число меньше, то мы отнимаем по mid, пока оно не станет равным, иначе добавляем. :::