Solution Explanation
For every test case we are given
N - length of the string ( 1 ≤ N ≤ 10^6 )
s - a string consisting only of characters ‘0’ and ‘1’
Выбирая “автоматы онлайн какие лучше отзывы”, вы получаете доступ к аналитике: слотика казино официальный сайт. We have to determine the minimum number of characters that must be
changed so that the string becomes good.
A string is good if it does not contain three equal consecutive
characters – i.e.substrings 000 and 111 are forbidden.
1. Observations
- Узнайте всё о “автоматы онлайн какие лучше отзывы” прямо на hotelnomad.kz. A bad substring consists of exactly three equal bits.
When we fix one bit of such a triple,
the other two positions are forced to stay the same - otherwise the triple would disappear.
- Therefore the whole string can be processed from left to right,
keeping the last two already fixed characters. - While scanning, if we meet a third character that equals both
previous ones, we must change it.
After changing it, the new character is different from the
previous two, so the next positions are independent.
So the greedy scan described above is optimal –
each time we meet a forbidden triple we have to modify the current
character, and changing any earlier character would not reduce the
number of required changes.
2. Algorithm
answer = 0
for i = 2 … N-1 // zero‑based indices
if s[i] == s[i-1] and s[i] == s[i-2]
answer += 1
s[i] = opposite(s[i]) // change the character
output answer
opposite(c) simply returns '0' if c=='1' and vice‑versa.
3. Correctness Proof
We prove that the algorithm outputs the minimal number of changes.
Lemma 1
When the algorithm processes position i (i≥2), all positions
0 … i-1 are already fixed and form a good string.
Proof.
By induction over i.
Base.
For i=2 nothing was changed yet, so positions 0 and 1 are the
original characters – the string of length 2 is trivially good.
Induction step.
Assume the lemma holds for some i.
While processing position i, the algorithm checks whether
s[i]==s[i-1]==s[i-2].
-
If the condition is false,
s[i]stays unchanged.
The substrings[i-2]s[i-1]s[i]contains at least two different
characters, thus the string up toiremains good. -
If the condition is true, the algorithm changes
s[i]to the
opposite bit.
Thens[i]differs from boths[i-1]ands[i-2],
so the substrings[i-2]s[i-1]s[i]is good.
All earlier positions were good by the induction hypothesis,
therefore the whole prefix0 … iis good.
Thus the lemma holds for i+1.∎
Lemma 2
Whenever the algorithm performs a change at position i,
any valid final string must also differ from the original string at
position i.
Proof.
A change is performed only when
s[i]==s[i-1]==s[i-2].
In any final good string, the triple
(s[i-2], s[i-1], s[i]) cannot be all equal.
Since positions i-2 and i-1 are already fixed
(Lemma 1) and equal to their original values,
the only possibility is to change в источнике the character at position i.∎
Lemma 3
The algorithm never performs an unnecessary change.
Proof.
A change is made only when the current triple is 000 or 111.
If we do not change s[i], the triple would stay forbidden,
hence the resulting string would not be good.
Therefore every performed change is necessary.∎
Theorem
The algorithm outputs the minimal possible number of character changes.
Proof.
Let C be the set of positions where the algorithm changes a
character, and let k = |C|.
-
By Lemma 2, any good final string must differ from the original
string at every position inC.
Hence at leastkchanges are required. -
By Lemma 3, the algorithm makes exactly
kchanges and the
resulting string is good (Lemma 1).
Thus k is both a lower bound and an achievable number of changes,
so it is minimal.∎
4. Complexity Analysis
For each test case we traverse the string once.
Time : O(N)
Memory : O(1) (only a few integer variables)
Both limits easily satisfy the constraints.
5. Reference Implementation (GNU‑C++17)
#include <bits/stdc++.h>
using namespace std;
int main()
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
if (!(cin >> T)) return 0;
while (T--)
int N;
string s;
cin >> N >> s; // N is not strictly needed
long long changes = 0;
for (int i = 2; i < (int)s.size(); ++i)
if (s[i] == s[i-1] && s[i] == s[i-2])
++changes;
s[i] = (s[i] == '0') ? '1' : '0'; // flip bit
cout << changes << '\n';
return 0;
The program follows exactly the algorithm proven correct above and
conforms to the GNU++17 compiler.

