436A - Feed with Candy
Автор разбора: Fefer_Ivan
В задача А типы съеденных конфет должны все время менятся. Так что первая съеденная конфета определяет тип всех последующих конфет. Возможных типа всего два, так что переберем тип первой съеденной конфеты. Пусть в какой-то момент времени Ом Ном должен съесть конфету типа t и может прыгать на высоту h. Очевидно, что наиболее выгодным решением будет съесть конфету с наибольшей массой среди всех конфет, которые Ом Ном может съесть на текущем этапе. Для решения задачи необходимо промоделировать процесс поедания конфет для начального h = x и t = [0, 1] и выбрать лучшее значение.
436B - Om Nom and Spiders
Автор разбора: Fefer_Ivan
Пронумеруем столбцы таблицы начиная с 0 слева направа, а строки начиная с 0 сверху вниз. Теперь заметим, что в момент времени t > 0 в клетке (x, y) могут находиться только 4 паука:
- Паук, который движется влево и в начале был в клетке (x, y + t).
- Паук, который движется вправо и в начале был в клетке (x, y - t).
- Паук, который движется вниз и в начале был в клетке (x - t, y).
- Паук, который движется вверх и в начале был в клетке (x + t, y).
Давайте переберем столбец в котором Ом Ном начнет свой путь. Пусть это столбец y. В момент времени 0 все пауки стоят на своих исходных позициях, а Ом Ном стоит в клетке (0, y). Так как на нулевой строке нет пауков, то в момент времени 0 Ом Ном их точно не встречает. Когда Ом Ном находится в клетке (x, y), это значит, что с момента начала движения прошло x единиц времени. Следовательно, для того, чтобы вычислить сколько пауков Ом Ном встретим в этой клетке, необходимо проверить лишь 4 клетки, указанные выше, на наличие паука, движущегося в нужном направлении.
436C - Dungeons and Candies
Автор разбора: Fefer_Ivan
Давайте рассмотрим неориентированный взвешенный граф, в котором k + 1 вершина. Пронумеруем вершины целыми числами от 0 до k. Вершины c 1 по k будут соответствовать уровни. Для каждой пары уровней i и j добавим ребро из i в j стоимость которого равно стоимости передачи одного уровня как разность с другим. Так же для каждого уровня i добавим ребро между вершиной 0 и i стоимости n·m, т.е. стоимости передачи уровня целиком. Каждый способ передать все уровни соответсвует остовному дереву в указанном графе. Таким обзаром необходимо вывести минимальное остовное дерево в этом графе.
436D - Pudding Monsters
Автор разбора: Fefer_Ivan
Задача решается при помощи динамического программирования. Введем обозначения: sum(l, r) — количество особых клеток на отрезке с l по r, zi — максимальное количество особых клеток, которые можно покрыть, используя только первые i монстров при условии, что i-тый монстр либо остается на месте, либо отправляется влево, di--- максимальное количество особых клеток, которые можно покрыть, используя только первые i монстров при условии, что i-тый монстр остается на месте.
Рассмотрим процесс вычисления di. Пусть i-тый монстр находится в клетке r. Переберем самую левую особую клетку, которая будет покрыта блоком монстров, в котором будет находиться i-й монстр. Пусть эта особая клетка находится в клетке l. Тогда нам требуется r - l дополнительных монстров отправить вправо для того, чтобы покрыть эту особую клетку. Тогда ответ будет равен zi - (r - l) + sum(l, r). Для вычисления di надо взять максимум по всем особым клеткам, левее i-того монстра.
Теперь, после того, как мы вычислили очередное значение di, необходимо обновить некоторые значения zj. Пусть i-тый монстр находится в клетке l. Переберем самую правую особую клетку, которая будет покрыта блоком монстров, в котором будет находиться i-й монстр. Пусть эта особая клетка находится в клетке r. Тогда нам требуется r - l дополнительных монстров отправить влево для того, чтобы покрыть эту особую клетку. Тогда, zi + (r - l) можно обновить следующим значением di + sum(l + 1, r). Так же необходимо не забыть обновить значение zi значением zi - 1.
Как можно видеть это решение имеет сложность O(n·m), так как для каждого из n монстров мы перебираем все m особых клеток, а все вычисления при фиксированной паре монстр-клетка проходят за O(1).
При реализации могут возникнуть небольшие тонкости, связанные с монстрами, которые уже в начальном состоянии слиплись в один блок.
436E - Cardboard Box
Автор разбора: Gerald
В задаче E нужно было написать правильную жадность. Правильных жадностей существует несколько, вот одна из них:
- Посмотрим на некоторый оптимальный ответ (набор как-то пройденных уровней). Отсортируем все уровни по b[i]. Если рассмотреть последний взятый в ответ уровень, пройденный на 2 звезды, то окажется, что все находящиеся до него в таком порядке уровни пройдены хотя бы на одну звезду. Иначе, можно было бы заменить этот уровень на какой-то не пройденный и не увеличить ответ.
- Пользуясь вышесказанным, зафиксируем префикс L уровней в порядке сортировки по b[i]. Все уровни этого префикса мы должны хоть как-то пройти (либо на 1, либо на 2 звезды). Дополнительно, будет считать, что все уровни пройденные на 2 звезды должны содержаться только в этом префиксе (такой префикс должен существовать для некоторого оптимального ответа, как было показано ранее).
- Так как мы зафиксировали префикс длиной L уровней, которые мы точно хоть как-то пройдем, можно сказать, что нам осталось добрать w - L звезд. Как мы можем добирать эти звезды? Либо допроходить какие-то уровни из префикса L на 2 звезды, либо проходить уровни не из префикса L на одну (потому что уровни, которые мы проходим на 2 звезды должны содержаться только на зафиксированном префиксе).
- Понятно, что для того, чтобы получить оптимальный ответ нужно выбрать w - L самых дешевых звезд. Поэтому отсортируем n элементов: L чисел b[i] - a[i] (для всех i ≤ L), n - L чисел a[i] (для всех i > L). Выберем среди этих чисел w - L минимальных.
Описанное нужно было реализовывать быстрее, чем за квадрат. Самая очевидная реализация использует декартово дерево, чуть менее очевидная использует дерево отрезков.
Итоговая сложность решения: O(n log n).
436F - Banners
Автор разбора: Gerald
Задача F была самой сложной задачей контеста. Чтобы лучше представить себе ее решение, можно перейти к геометрическому представлению задачи. Представим, что люди — это точки на плоскости Opc, тогда, то что требуется найти — для каждой прямой c = i, такую прямую p = j, что некоторая функция принимает максимальное значение. Под некоторой функцией понимается следующая: (количество точек не ниже прямой c = i умножить на w·i) плюс (количество точек ниже прямой c = i и не левее прямой p = j умножить на j).
Будем двигать сканирующую прямую снизу вверх. Сначала рассматриваем c = 0, затем c = 1 и так далее. При этом для каждого p будем хранить величину d[p] — чему равен ответ на задачу при текущем c, если второй параметр будет равен p. Если у нас есть корректно посчитанный массив d[] и мы переходим от c к c + 1, как пересчитать этот массив для нового c?
Посмотрим на всех людей, для которых хоть что-то поменяется, очевидно — это люди у которых b[i] = c. При текущем c они еще пользовались бесплатной версией, но после увеличения на 1, они перестанут ей пользоваться. Понятно, что каждый такой человек i модифицирует массив следующим образом: d[1] + = 1, d[2] + = 2, ..., d[b[i]] + = b[i].
Теперь можно переформулировать задачу в терминах структур данных. Есть два вида запросов: прибавить на префиксе возрастающую арифметическую прогрессию, узнать максимум среди всех элементов массива d. Один из способов решить такую задачу — корневая декомпозиция.
Разобьем все запросы на группы по sqrt(q) штук, в каждой группе выделим отрезки, на которых к ячейке d[i] значение i прибавляется с одним и тем же коэффициентом. Для каждого такого отрезка построим нижнее огибающее множество прямых y = d[i] + i·x. Так как запросов в группе sqrt(q), то и отрезков будет O(sqrt(q)). Значит прибавление на префиксе и взятие максимума можно будет делать за O(sqrt(q)).
Итоговая сложность решения: O(MAXX·sqrt(MAXX)), где MAXX — максимальное значение среди a[i] и b[i].
Во второй задаче можно ещё заметить, что с любым конкретным пауком мы можем встретиться только в какой-то одной клетке. Если быть точным — с движущимися вниз мы не встретимся, с движущимися вверх встретимся в том же столбце, но только если они в четной строке. С движущимися влево и вправо мы можем встретиться только в столбцах с номерами j-i и j+i соответственно. (Все описанное — в нуль-индексации)
please hurry to write the report about other question.
Very offensive statement...
Yes.It's too rude
You need to be banned for having multiple accounts.
It's sad that this comment has too many negative votes. worfzyq 's initial comment was "Sorry", which may imply that he was also quakerzyq.
AlexanderBolshakov probably meant that, which is understandable. worfzyq should get negative votes for completely changed the meaning of his comment instead..
Also: 6801504 6883269
Now I understand that anything that is written here should be written in such a way that even those who don't like to think (or can't do this) will still understand what you've meant. And this is really sad.
Well, just like on habrahabr :)
Why so hurry? Solving these 3 problems are very enough for a high rank in this contest... (at least to increase my rating to be red! :))
lol I just got red after Zepto Code round, too! I'm looking forward to seeing you at Taiwan.
Haha congrats. Vietnamese IOI team have a red coder then :) Unfortunately I won't go to Taiwan. IOI 2013 is my last IOI :( Now my world is ACM-ICPC :) Well let's meet at other opportunity :)
You should go to NUS next year to see him :)
Images in the problem statements were so good that I wish they (or similar ones) were present in the editorials too ;)
Anudeep, Its very unfortunate that ur problem A failed otherwise you would have been in top 50.Hard luck,bro.:(
I have this habit of locking a solution as soon as i submit. I did the same with A. Then when I was implementing B (or C), I understood that my A will fail, quickly finished that problem and started hacking solutions with a case that my solution will fail. There were many others who did the same mistake, Got 7 hacks ;)
I'm surprised that C can be solved by bruteforce :O
My solution for problem E:
Consider the levels with ascending a(i) and iterate through them. Let's say, we're now at level i, we have some decision to make here:
Choose 0 star here. It's easy to see that from now on, if we choose a 1-star level, let's call j, we have a(j)>a(i), which make swapping i and j lead to a better solution. So from now on we only choose 2-stars levels. Among all the remaining levels, we choose the ones with b(i) minimum to satisfy the required stars.
Choose 1 star here. Create a fake level with a=b(i)-a(i), b=+inf. Insert that fake level in our box.
To maintain the levels and take out the one with minimum a(i), we can use a heap (priority_queue) with two value a(i) and b(i).
Awesome, coupled with noticing that you resolve the issue of adding the cost of all minimun b(i) with a Fenwick tree, I managed to get a working solution Thank you, have my like.
Can someone show a short Java implementation of C using minimum spanning trees?
http://mirror.codeforces.com/contest/436/submission/6876229
Guys why the answer of the last example of 436D - Pudding Monsters is 1? Do we count the number of covered stars only when all the monsters combine in a single block? Can an optimal game finish before we combine them all?
We can stop the game at any time. Even if we did not make a single move. In the second example seconds and third monsters are already merged in one block and can not be separated.
with D can O(n*m) pass the systest? i thought the complexitiy is too large so used much time to think of wrong O(m^2 lg n) sol
Yes, time limit is 5 seconds bro.
It is only 2·108. And operations are pretty simple. Integer addition and multiplication in straight-forward for-loops. My solution in C++ runs only 500 ms.
Here comes a line I'm often repeating: "Algorithmic problems are divided into two groups. Those were n log n TLEs for n<=10^6 and those were organizers say "It is only 2*10^8, today's computer do it in a 0,5s"" :P. Indeed in a very short period I experienced also my O(n log n) submission TLEing and my "favorite" organizer's excuse for ridiculously big constraints.
It is known, that there is always a constant multiplier behind big-O notation. One can not just ignore it. In this problem thr constant is small. In FFT algorithm, for example, it is bigger.
In World Finals problem D had 25*25*10^6 ~ 6*10^8 solution that can or can not pass the tests depending on implementation. We experienced both options.
I spent a few hours on Problem C to figure out how to find minimum spanning tree, so I decided to share what I've found out.
If you don't know how to find minimal spanning tree, this tutorial on YouTube will be really helpful.
I implemented my solution based on this editorial and the tutorial. I hope this helps if you are having trouble understanding/implementing!
can you explain me this : MST is O((n*M*k)^2) which will go out of time bound ?
Kruskal's algorithm of minimum spanning tree runs in O(logE) time, and here maximum value of E is 10^3 * 10^3. Therefore, it will not exceed time limit. A better question to ask would be how building the graph would not exceed time limit-it takes around 10^8 operations, and while in here it does fit in time limit, I've seen other judges where it might've timed out.
Задача F. Что такое огибающее множество прямых,и в чем их смысл? И как находить ответ, имея это множество? Я знаю что такое sqrt-декомпозиция, но не очень понимаю как её сюда на эту задачу натянули) Может кто-нибудь поподробней объяснить? )
@Fefer_Ivan can you please provide the links to the solutions of the above problems(specially to the D and E)??
http://mirror.codeforces.com/contest/436/status/F http://mirror.codeforces.com/contest/436/status/E
thank you for the link, But I was looking for the editorial author's solution so that I can understand concept in the editorial and how they implemented it.
Кто нибудь устроился в ZEPTOLAB? Как собеседование проходит? Какие вопросы задают? =))
По задаче Е.
Пользуясь вышесказанным, зафиксируем префикс L уровней в порядке сортировки по b[i]. Все уровни этого префикса мы должны хоть как-то пройти
Какие именно элементы с префикса L мы должны выбрать для прохождения на две звезды?
Берем все с префикса по 1 звезды. Затем кое-кого берем с префикса и переводим с 1 звезды на 2 ИЛИ берем кого-то НЕ с префикса на 1 звезду. Стоимость такой штуки для префикса = (b-a), для не префикса = a. Выбираем самые дешевые звездочки. Их кол-во (w-l)