<p>You are given an <code>m x n</code> binary matrix <code>grid</code>.</p>

<p>A row or column is considered <strong>palindromic</strong> if its values read the same forward and backward.</p>

<p>You can <strong>flip</strong> any number of cells in <code>grid</code> from <code>0</code> to <code>1</code>, or from <code>1</code> to <code>0</code>.</p>

<p>Return the <strong>minimum</strong> number of cells that need to be flipped to make <strong>all</strong> rows and columns <strong>palindromic</strong>, and the total number of <code>1</code>&#39;s in <code>grid</code> <strong>divisible</strong> by <code>4</code>.</p>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">grid = [[1,0,0],[0,1,0],[0,0,1]]</span></p>

<p><strong>Output:</strong> <span class="example-io">3</span></p>

<p><strong>Explanation:</strong></p>

<p><img src="https://assets.leetcode.com/uploads/2024/08/01/image.png" style="width: 400px; height: 105px;" /></p>
</div>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">grid = [[0,1],[0,1],[0,0]]</span></p>

<p><strong>Output:</strong> <span class="example-io">2</span></p>

<p><strong>Explanation:</strong></p>

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/07/08/screenshot-from-2024-07-09-01-37-48.png" style="width: 300px; height: 104px;" /></p>
</div>

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

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">grid = [[1],[1]]</span></p>

<p><strong>Output:</strong> <span class="example-io">2</span></p>

<p><strong>Explanation:</strong></p>

<p><img alt="" src="https://assets.leetcode.com/uploads/2024/08/01/screenshot-from-2024-08-01-23-05-26.png" style="width: 200px; height: 70px;" /></p>
</div>

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

<ul>
	<li><code>m == grid.length</code></li>
	<li><code>n == grid[i].length</code></li>
	<li><code>1 &lt;= m * n &lt;= 2 * 10<sup>5</sup></code></li>
	<li><code>0 &lt;= grid[i][j] &lt;= 1</code></li>
</ul>

class Solution:
    def heapify(arr, n, i):
        largest = i
        l = 2 * i + 1
        r = 2 * i + 2

        if l < n and arr[l] > arr[largest]:
            largest = l

        if r < n and arr[r] > arr[largest]:
            largest = r

        if largest != i:
            arr[i], arr[largest] = arr[largest], arr[i]
            heapify(arr, n, largest)

    def heapSort(arr):
        n = len(arr)
        for i in range(n // 2 - 1, -1, -1):
            heapify(arr, n, i)

        for i in range(n - 1, 0, -1):
            arr[0], arr[i] = arr[i], arr[0]
            heapify(arr, i, 0)

    def partition(arr, start, end):
        index = 0
        pivotElement = arr[end]
        pivotIndex = 0
        temp = [0] * (end - start + 1)

        for i in range(start, end + 1):
            if arr[i] < pivotElement:
                temp[index] = arr[i]
                index += 1

        temp[index] = pivotElement
        index += 1

        for i in range(start, end):
            if arr[i] > pivotElement:
                temp[index] = arr[i]
                index += 1

        index = 0
        for i in range(start, end + 1):
            if arr[i] == pivotElement:
                pivotIndex = i
            arr[i] = temp[index]
            index += 1
        return pivotIndex
    
    def minimumCost(self, target: str, words: List[str], costs: List[int]) -> int:
        n = len(target)
        m = len(words)

        wc = {}
        for i, w in enumerate(words):
            wc[w] = min(wc.get(w, float('inf')), costs[i])

        dp = [float('inf')] * (n + 1)
        dp[0] = 0

        for i in range(1, n + 1):
            for w in wc:
                if i >= len(w) and target[i - len(w):i] == w:
                    dp[i] = min(dp[i], dp[i - len(w)] + wc[w])

        return dp[n] if dp[n] != float('inf') else -1
    def quickSort(arr, start, end):
        if start < end:
            partitionIndex = partition(arr, start, end)
            quickSort(arr, start, partitionIndex - 1)
            quickSort(arr, partitionIndex + 1, end)
 
    def getMax(arr):
        mx = arr[0]
        for i in range(1, len(arr)):
            if arr[i] > mx:
                mx = arr[i]
        return mx

    def countSort(arr, exp):
        n = len(arr)
        output = [0] * n
        count = [0] * 10

        for i in range(n):
            count[(arr[i] // exp) % 10] += 1

        for i in range(1, 10):
            count[i] += count[i - 1]

        for i in range(n - 1, -1, -1):
            output[count[(arr[i] // exp) % 10] - 1] = arr[i]
            count[(arr[i] // exp) % 10] -= 1

        for i in range(n):
            arr[i] = output[i]
    
    def minimumCost(self, m: int, n: int, horizontalCut: List[int], verticalCut: List[int]) -> int:
        horizontalCut.sort()
        verticalCut.sort()
        
        h_segments = len(horizontalCut) + 1
        v_segments = len(verticalCut) + 1
        
        total_cost = 0
        
        i, j = 0, 0
        while i < len(horizontalCut) and j < len(verticalCut):
            if horizontalCut[i] < verticalCut[j]:
                total_cost += horizontalCut[i] * v_segments
                h_segments -= 1
                i += 1
            else:
                total_cost += verticalCut[j] * h_segments
                v_segments -= 1
                j += 1
        
        while i < len(horizontalCut):
            total_cost += horizontalCut[i] * v_segments
            i += 1
        
        while j < len(verticalCut):
            total_cost += verticalCut[j] * h_segments
            j += 1
        
        return total_cost

    def minChanges(self, nums: List[int], k: int) -> int:
        m = {}
        v = []

        for i in range(len(nums) // 2):
            a = nums[i]
            b = nums[len(nums) - i - 1]
            diff = abs(a - b)

            X = max(a, b, k - a, k - b)

            if diff in m:
                m[diff].append(X)
            else:
                m[diff] = [X]
            v.append(X)

        ans = len(nums)
        v.sort()

        for diff, values in m.items():
            T = bisect.bisect_left(v, diff)
            T = T * 2 + (len(nums) // 2 - T)

            for X in values:
                if X < diff:
                    T -= 2
                else:
                    T -= 1

            ans = min(ans, T)

        return ans

    def minimumOperations(self, nums: List[int], target: List[int]) -> int:
        n = len(nums)
        t = [0] * n
        for i in range(n):
            t[i] = target[i] - nums[i]
        
        pos = 0
        m = 0
        ans = abs(t[0])
        m = ans
        
        if t[0] >= 0:
            pos = 1
        
        for i in range(1, n):
            if t[i] < 0 and pos == 1:
                ans += abs(t[i])
                m = abs(t[i])
                pos = 0
                continue
            if t[i] >= 0 and pos == 0:
                ans += abs(t[i])
                m = abs(t[i])
                pos = 1
                continue
            if m >= abs(t[i]):
                m = abs(t[i])
                continue
            else:
                ans += abs(t[i]) - m
                m = abs(t[i])
        
        return ans

    def isprime(self, n):
        if n <= 1:
            return False
        for i in range(2, int(math.sqrt(n)) + 1):
            if n % i == 0:
                return False
        return True
    
    def nonSpecialCount(self, l, r):
        ans = r - l + 1
        cur = 3
        if 4 >= l and 4 <= r:
            ans -= 1
        while True:
            val = cur * cur
            if val > r:
                break
            if self.isprime(cur) and val >= l and val <= r:
                ans -= 1
            cur += 2
        return ans
    def minFlips(self, grid):
        n = len(grid)
        m = len(grid[0])
        ans = 0
        
        if n % 2 == 1 and m % 2 == 1:
            if grid[n // 2][m // 2] == 1:
                ans += 1

        shift = [0] * 3
        if n % 2 == 1:
            a, b = 0, m - 1
            while a < b:
                sm = grid[n // 2][a] + grid[n // 2][b]
                shift[sm] += 1
                a += 1
                b -= 1

        if m % 2 == 1:
            a, b = 0, n - 1
            while a < b:
                sm = grid[a][m // 2] + grid[b][m // 2]
                shift[sm] += 1
                a += 1
                b -= 1

        if shift[2] % 2 == 1:
            if shift[1] > 0:
                ans += shift[1]
            else:
                ans += 2
        else:
            ans += shift[1]

        for i in range(n // 2):
            for j in range(m // 2):
                a = grid[i][j]
                b = grid[n - 1 - i][j]
                c = grid[i][m - 1 - j]
                d = grid[n - 1 - i][m - 1 - j]

                sm = a + b + c + d

                if sm != 0 and sm != 4:
                    ans += min(sm, 4 - sm)

        return ans

70900