Editorial for IOI '16 P5 - Unscrambling a Messy Bug


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Subtask 1 allows you to check all 2n possible elements, so it can be solved by various solutions. For example, you can add 2n1 random elements in your set, check all elements, try all n(n1)2 transpositions and check that it will give you the same result.

Subtask 2 may be solved by a simple solution, using at most n add_element operations and at most n(n1)2 check_element operations.

  • Let's add n elements into the set, ith element will have first i bits set to one.
Copy
add_element("10000000")
add_element("11000000")
add_element("11100000")
add_element("11110000")
add_element("11111000")
add_element("11111100")
add_element("11111110")
add_element("11111111")
  • Now we will get positions of bits one by one. First, let's find the position of bit 0. This can be done using at most n1 queries:
Copy
check_element("10000000") returned false
check_element("01000000") returned false
check_element("00100000") returned false
check_element("00010000") returned false
check_element("00001000") returned false
check_element("00000100") returned true
  • Now we know the position of bit 0 and want to find the position of bit 1. This can be done using at most n2 queries:
Copy
check_element("10000100") returned false
check_element("01000100") returned false
check_element("00100100") returned false
check_element("00010100") returned true
  • And so on, we can find position of ith bit using ni1 queries, so the total number of queries in the worst case is n(n1)2=496.

Subtask 3 can be solved by several optimizations of the previous algorithm. The simplest one is to shuffle the order of bytes. This will give us the average number of queries n(n1)4=248, which was enough to pass the tests.

Subtasks 4 and 5 require an O(nlogn) solution, in subtask 4 you can make at most 2nlogn operations of each type, in subtask 5 you can make only nlogn operations.

Subtask 5 may be solved using divide and conquer technique. Let's try to split all bits into two halves using n requests, and solve the problem for each half independently. In this solution, we will make at most nlog2n operations of each type.

  • To split a group of bits into two halves, we will add into set n2 elements, ith element will have ith bit set to one, all other set to zero:
Copy
add_element("10000000")
add_element("01000000")
add_element("00100000")
add_element("00010000")
  • After this, we will check n elements with a single bit set to one. For example:
Copy
check_element("10000000") returned false
check_element("01000000") returned true
check_element("00100000") returned false
check_element("00010000") returned false
check_element("00001000") returned true
check_element("00000100") returned true
check_element("00000010") returned false
check_element("00000001") returned true
  • Now we know which n2 bits correspond to the first n2 bits. In this example, we know that bits 1, 4, 5, and 7 correspond to bits 03. So now we will solve the same problem for them only, and after that solve the problem for other n2 bits.

  • In order to solve the problem for some subset of bits, we need to make sure that the elements we use in different subproblems are distinct. We can achieve this by setting all bits that are not in our subset to ones. For example, when we want to split bits 03 into halves, we will make the following operations.

Copy
add_element("10001111")
add_element("01001111")

check_element("11110010")
check_element("10111010")
check_element("10110110")
check_element("10110011")

Comments

There are no comments at the moment.