Привет всем!
UPD: Разбор постепенно появляется на английском языке.
556A - Дело о нулях и единицах
If there still exist at least one 0 and at least one 1 in the string then there obviously exists either substring 01 or substring 10 (or both) and we can remove it. The order in which we remove substrings is unimportant: in any case we will make max(#zeros, #ones) such operations. Thus the answer is |#ones - #zeros|.
Time: O(n).
556B - Дело о поддельных шестеренках
Notice that after pressing the button n times gears return to initial state. So the easiest solution is to simulate the process of pressing the button n times and if at some step the active teeth sequence is 0, 1, ... , n - 1 output "Yes" else "No". But this solution can be improved. For instance, knowing the active tooth of the first gear you can quickly determine how many times pressing the button is necessary, go to that state and check the sequence only once.
Time: O(n) or O(n2); solutions: 11822751 (O(n)) and 11822759 (O(n2))
Suppose we don't need to disassemble some sequence of dolls. Then no doll can be inserted into no doll from this chain. So we don't need to disassemble a sequence of dolls only if they are consecutive and start from 1. Let the length of this chain be l. Then we will need to get one doll from another n - k - l + 1 times. Now we have a sequence 1 → 2 → ... → l and all other dolls by themselves. n - l + 1 chains in total so we need to put one doll into another n - l times. 2n - k - l + 1 operations in total.
Time: O(n); solution: 11823230.
We can put a bridge between bridges i and i + 1 if its length lies in the segment [li + 1 - ri;ri + 1 - li]. Now we have a well-known problem: there are n - 1 segments and m points on a plane, for every segment we need to assign a point which lies in it to this segment and every point can be assigned only once.
Let's call a segment open if no point is assigned to it. Let's go through all points from left to right and at every moment keep all open segments that contain current point in a BST (std::set). When processing a point it should be assigned to the segment (from our set) that has the leftmost right end.
This algorithm will find the answer if there is one. Suppose this solution is wrong and suppose there is a solution in which point A is assigned to another open segment (there's no sense in skipping this point). Then some point B is assigned to the segment which A was assigned to. B is to the right of A so we can swap them and come to our answer again.
Time: O((n + m)log(n + m)); solution: 11823764.
Let's solve this problem with two segment trees: we'll keep the lowest eaten piece for each column in one of them and the leftmost eaten piece for each row in another. Suppose we have a query x y L. Position where we'll stop eating chocolate is stored in the row segment tree so we can easily find the number of eaten pieces. After that we need to update both segment trees.
n is rather big in this problem. One way to deal with it is to use coordinate compression. Another is to use implicit segment trees.
Time: O(qlogq) or O(qlogn); solutions: 11824011 and 11824029.