PROBLEM LINK:
Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4
Author & Tester: tabr
Editorialist: iceknight1093
DIFFICULTY:
TBD
PREREQUISITES:
None
PROBLEM:
You’re given a string binary S. In one move, you can replace a substring of length 3 by "100"
.
Find the lexicographically smallest string you can attain.
EXPLANATION:
Let k be the first occurrence of \texttt{1} in S, i.e, the smallest index such that S_k = \texttt{1} . If no ones exist in the string, let k = N+1 instead.
In particular, S_i = \texttt{0} for all 1 \leq i \lt k.
Note that it’s never optimal to perform an operation involving an index \lt k, because we would replace a prefix zero with a 1, and that isn’t optimal for lexicographical smallness.
So, we only perform replacement operations on substrings that start at indices \geq k.
Now, a simple analysis of this should tell you that:
- If k \gt N-2, then it’s not possible to even perform a move; so the optimal solution is to do nothing and just print S.
- If k \leq N-2, then we can perform replacement operations on some substrings.
Here, we can in fact make S_i = \texttt{0} for every i \gt k via the following process:- Perform the replacement operation on substring S_iS_{i+1}S_{i+2} in decreasing order of i, starting from i = N-2 and going down to i = k.
It’s easy to see that:- The first move sets S_N = S_{N-1} = \texttt{0}.
- The second move sets S_{N-2} = \texttt{0} without changing anything to its right.
- The second move sets S_{N-3} = \texttt{0} without changing anything to its right.
\vdots
- Perform the replacement operation on substring S_iS_{i+1}S_{i+2} in decreasing order of i, starting from i = N-2 and going down to i = k.
In fact, in the second case we set every character of S to zero except S_k, and it’s easy to see why this is the lexicographically smallest string possible - making S_k zero using an operation would make some character to the left of S_k change from 0 to 1, and that’s not optimal.
TIME COMPLEXITY
\mathcal{O}(N) per testcase.
CODE:
Author's code (C++)
#include <bits/stdc++.h>
using namespace std;
int main() {
int tt;
cin >> tt;
while (tt--) {
int n;
cin >> n;
string s;
cin >> s;
int i = (int) (find(s.begin(), s.end(), '1') - s.begin());
if (i <= n - 3) {
for (int j = i + 1; j < n; j++) {
s[j] = '0';
}
}
cout << s << " \n";
}
return 0;
}
Editorialist's code (Python)
for _ in range(int(input())):
n = int(input())
s = input()
for i in range(n-2):
if s[i] == '1':
s = s[:i] + '1' + '0'*(n-i-1)
break
print(s)