PROBLEM LINK:
Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4
Author: pols_agyi_pols
Tester: kingmessi
Editorialist: iceknight1093
DIFFICULTY:
Simple
PREREQUISITES:
None
PROBLEM:
You’re given binary strings A and B of the same length.
In one move, you can choose a substring of A that contains exactly one occurrence of 1 and reverse it.
Find the minimum moves to convert A into B; print -1 if it’s not possible to do so.
EXPLANATION:
Our operation doesn’t allow us to change the number of zeros and ones in A.
So, if we want A = B in the end, A and B must have the same number of zeros and ones to begin with too.
If their counts differ, the answer is hence immediately -1.
On the other hand, if A and B have the same number of ones initially, it’s always possible to make them equal (because, for example, the operation allows us to swap adjacent unequal characters; so any rearrangement can be reached.)
So, when A and B have the same number of ones, we only need to focus on finding the minimum number of operations needed.
Each operation, we are able to reverse a substring that contains a single 1.
Note that this means:
- We can only move around a single occurrence of 1 at a time; and
- Different occurrences of 1 cannot ‘cross’ each other.
Suppose there are k ones in both strings.
Let them be at indices x_1 \lt x_2 \lt\ldots\lt x_k in A and y_1 \lt y_2\lt\ldots\lt y_k in B.
Then, since occurrences of 1 cannot cross each other, the occurrence at index x_i must eventually end up at index y_i.
Since we can only move a single occurrence at a time, a lower bound on the answer is certainly just the count of i such that x_i \ne y_i.
This lower bound is indeed attainable.
Proof
We’ll prove that there always exists a move that fixes a 1 in place.
If k = 0 then no moves are needed.
If k = 1 then there’s only one 1, and the operation allows us to move it around freely; so obviously one operation is enough.
Now assume k \ge 2.If x_i = y_i for some index i, we can then solve independently for the ranges [1, x_i-1] and [x_i+1, N] of the string.
So, we assume this is not the case for any i.If x_1 \gt y_1, then everything to the left of index x_1 in A is a 0.
This means we can just reverse the segment [y_1, x_1] in A, and the 1 at x_1 will move to y_1, fixing it in place.
Similarly, if x_k \lt y_k, we can reverse [x_k, y_k] to fix the last 1 in place.So, the only interesting case is when x_1 \lt y_1 and x_k \gt y_k.
However, in this case there must exist some index i such that x_i \lt y_i but x_{i+1} \gt y_{i+1}.
When this happens, everything from x_i+1 to x_{i+1}-1 contains only zeros in A.
In particular, note that this range contains indices y_i and y_{i+1}.
This allows us to reverse [x_i, y_i] freely, fixing a 1 at index y_i as required.
Now we can once again solve for the left and right of this index independently.This proves our claim that there’s always a move that fixes a previously-unfixed 1, hence the answer is the number of unfixed ones.
The final solution is hence quite simple:
- If A and B have different counts of 1, the answer is -1.
Otherwise, they have equal counts - say k. - Let x_1 \lt \ldots\lt x_k be the positions of ones in A.
- Let y_1 \lt \ldots\lt y_k be the positions of ones in B.
- The answer is the count of i such that x_i \ne y_i.
TIME COMPLEXITY:
\mathcal{O}(N) per testcase.
CODE:
Editorialist's code (PyPy3)
for _ in range(int(input())):
n = int(input())
a = input()
b = input()
aone, bone = [], []
for i in range(n):
if a[i] == '1': aone.append(i)
if b[i] == '1': bone.append(i)
if len(aone) != len(bone):
print(-1)
continue
diff = 0
for i in range(len(aone)):
diff += aone[i] != bone[i]
print(diff)