Editorial for CCO '23 P4 - Flip it and Stick it
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
The overall approach is to do casework on all possible . In each case, we first characterize all the strings that do not contain (call these good states). Based on this characterization, we then look for a measure of how far is from a good state and a greedy algorithm that repeatedly brings closer to a good state.
Formally, in each of the cases, we will find a function such that at all good states, for all where is obtained from by one reversal, and a greedy algorithm that finds an from any non-good state such that . It will then follow that is the answer for any string .
We can reduce the number of cases by half by noting that the answer remains the same if all the bits in and are flipped, so we may WLOG let .
Subtask 1
We need to consider the case .
A good state is when the string is composed of only s. Therefore the answer is if contains only s, and otherwise, the answer is .
Subtask 2
We need to consider the case .
A good state is when the string is a block of consecutive s followed by a block of consecutive s. This encourages us to look at blocks of consecutive s, and we might conjecture that the answer is the number of blocks of consecutive s that are not at the beginning of . Indeed, this number can decrease by at most per reversal, and a greedy algorithm that looks for the first block of s that is not at the beginning and performs a reversal to combine it with the beginning (e.g. or ) works.
Alternatively, the answer is just the number of times appears in as a substring, which can be proven similarly.
Subtask 3
We need to consider the case .
A good state is when the string does not contain any blocks of two or more consecutive s. If has more s than the number of s plus , then the answer is since no rearrangement of the characters of is a good state.
Otherwise, the answer is the sum of over all blocks of consecutive s. Whenever is not a good state, there exists a substring in , and we can greedily perform a reversal to "cut off" a from a block and "insert" it into this (e.g. ).
Alternatively, the answer is just the number of times appears in as a substring if , otherwise .
Subtask 4
We need to consider the cases and . By reversing and flipping the bits of and , these cases are equivalent, so we will only describe .
A good state is when the string has a prefix of consecutive s and no blocks of two or more consecutive s after that. The answer is the number of blocks of two or more consecutive s that are not in the prefix of s, and a greedy algorithm similar to can prove this.
Alternatively, the answer is just the number of times appears in as a substring.
Subtask 5
We need to consider the cases and . The case was solved in subtask 4, so we need to solve .
A good state is when the string does not contain any blocks of exactly one consecutive . In one reversal, it is possible to "merge" up to blocks of exactly one (e.g. ). Therefore, if contains blocks of exactly one consecutive , the answer is .
Alternatively, the answer is just the number of times appears in as a substring divided by , rounded up.
Subtask 6
The remaining case is when .
Similar to when , a good state is when the string does not contain any blocks of three or more consecutive s. If has more s than twice the number of s plus , then the answer is since no rearrangement of the characters of is a good state.
In this case, it might help to analyze how reversals behave on the blocks of s in more closely. Suppose the s in separate into blocks of consecutive s, where some may be zero. Then a reversal takes any two (where ), changes them to two new block sizes (where any is possible), and reverses the order of the blocks in between and . We can view as a multiset since the order is not important.
We can use blocks of size to cut off pieces of size from larger blocks, and we can also use blocks of size to cut off pieces of size from larger blocks. Intuitively, we should use the size blocks to cut off pieces of size from the largest blocks, since this is the most efficient, and only use size blocks if necessary. This leads to the following greedy algorithm: while the largest block has size , use a size block if there is one (replace with ), otherwise use a size block (replace with ).
The correctness of this greedy algorithm can be proven by finding an explicit function describing the answer. Without size blocks, the answer would be . With arbitrarily many size blocks, we can save up to reversals by cutting off at a time instead of . Thus, we conjecture that the answer is . It is straightforward to check that can decrease by at most per reversal, and the greedy algorithm above gives a way to always decrease by until a good state is reached, so this is indeed the answer.
Comments