<p>You are given a <strong>0-indexed</strong> binary string <code>s</code> of length <code>n</code> on which you can apply two types of operations:</p>

<ul>
	<li>Choose an index <code>i</code> and invert all characters from&nbsp;index <code>0</code> to index <code>i</code>&nbsp;(both inclusive), with a cost of <code>i + 1</code></li>
	<li>Choose an index <code>i</code> and invert all characters&nbsp;from&nbsp;index <code>i</code> to index <code>n - 1</code>&nbsp;(both inclusive), with a cost of <code>n - i</code></li>
</ul>

<p>Return <em>the <strong>minimum cost </strong>to make all characters of the string <strong>equal</strong></em>.</p>

<p><strong>Invert</strong> a character means&nbsp;if its value is &#39;0&#39; it becomes &#39;1&#39; and vice-versa.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;0011&quot;
<strong>Output:</strong> 2
<strong>Explanation:</strong> Apply the second operation with <code>i = 2</code> to obtain <code>s = &quot;0000&quot; for a cost of 2</code>. It can be shown that 2 is the minimum cost to make all characters equal.
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> s = &quot;010101&quot;
<strong>Output:</strong> 9
<strong>Explanation:</strong> Apply the first operation with i = 2 to obtain s = &quot;101101&quot; for a cost of 3.
Apply the first operation with i = 1 to obtain s = &quot;011101&quot; for a cost of 2. 
Apply the first operation with i = 0 to obtain s = &quot;111101&quot; for a cost of 1. 
Apply the second operation with i = 4 to obtain s = &quot;111110&quot; for a cost of 2.
Apply the second operation with i = 5 to obtain s = &quot;111111&quot; for a cost of 1. 
The total cost to make all characters equal is 9. It can be shown that 9 is the minimum cost to make all characters equal.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s.length == n &lt;= 10<sup>5</sup></code></li>
	<li><code>s[i]</code> is either <code>&#39;0&#39;</code> or <code>&#39;1&#39;</code></li>
</ul>

class Solution:
    def minimumCost(self, s: str) -> int:

        # m1: compute prefix and suffix arrays
        # prefix[i] = cost to turn all characters from 0 to i equal to s[i]
        # suffix[i] = cost to turn all characters from i to n - 1 equal to s[i]

        n = len(s)
        pre, suf = [0] * n, [0] * n

        for i in range(1, n):
            if s[i] == s[i - 1]:
                pre[i] = pre[i - 1]
            else:
                # i.e. 01, then we get pre[i - 1] (till 0) and flip at i - 1 (cost = i - 1 + 1 = i)
                pre[i] = pre[i - 1] + i
        
        minCost = math.inf

        for i in range(n - 2, -1, -1):
            if s[i] == s[i + 1]:
                suf[i] = suf[i + 1]
            else:
                # flip from i + 1, so cost is n - (i + 1) = n - i - 1
                suf[i] = suf[i + 1] + n - i - 1
        #     minCost = min(minCost, pre[i] + suf[i])

        # return min(minCost, suf[0])

        for i in range(n):
            minCost = min(minCost, pre[i] + suf[i])
        
        return minCost

        # m2: dp
        # dp[i] = min cost to make first i characters in the string equal

        # res = 0
        # n = len(s)
        # for i in range(1, n):
        #     if s[i] != s[i - 1]:
        #         # flip prefix or suffix
        #         res += min(i, n - i)

        # min(1, 5) = 1
        # min(2, 4) = 2

        # res = 1 + 2 + 3 + 2 + 1

        
        # return res



# my solution:
#         # operation 1 on i = 1 => cost = 2; 100101
#         # operation 1 on i = 0 => cost = 1; 000101
#         # operation 2 on i = 3 => cost = 6 - 3 = 3; 000010
#         # opertion 2 on i = 4 => cost = 6 - 4 = 2; 000001
#         # operation 2 on i = 5 => cost = 6 - 5 = 1; 000000
        
#         # if i < n/2, use operation 1
#         # if i > n/2, use operation 2
        
#         # when i + 1 < n - i => 2 i < n - 1 => i < (n - 1) / 2

#         n = len(s)
#         cost_0, cost_1 = 0, 0
#         parity_0, parity_1 = 0, 0

#         for i in range((n - 1) // 2, -1, -1):
#             if s[i] == '0':
#                 if parity_1 % 2 == 0:
#                     cost_1 += i + 1
#                     parity_1 += 1
#                 if parity_0 % 2 == 1:
#                     cost_0 += i + 1
#                     parity_0 += 1
#             if s[i] == '1':
#                 if parity_0 % 2 == 0:
#                     cost_0 += i + 1
#                     parity_0 += 1
#                 if parity_1 % 2 == 1:
#                     cost_1 += i + 1
#                     parity_1 += 1

#         parity_0, parity_1 = 0, 0
#         for i in range((n - 1) // 2 + 1, n):
#             if s[i] == '0':
#                 if parity_1 % 2 == 0:
#                     cost_1 += n - i
#                     parity_1 += 1
#                 if parity_0 % 2 == 1:
#                     cost_0 += n - i
#                     parity_0 += 1
#             if s[i] == '1':
#                 if parity_0 % 2 == 0:
#                     cost_0 += n - i
#                     parity_0 += 1
#                 if parity_1 % 2 == 1:
#                     cost_1 += n - i
#                     parity_1 += 1
#         return min(cost_0, cost_1)

279