<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 minFlips(self, grid: List[List[int]]) -> int:
        NR  = len(grid)
        NC = len(grid[0])
        group_size = defaultdict(lambda: 0)
        group_count1 =  defaultdict(lambda : 0)
        group_count0 =  defaultdict(lambda : 0)
        cnt = defaultdict(lambda : 0)
        for r in range(NR):
            for c in range(NC):
                cell = grid[r][c]
                rr = min (r , NR-1 - r)
                cc = min (c , NC-1 - c)
                cnt[cell] +=1
                group_id =(rr,cc)
                group_size[group_id] +=1
                if(cell == 1):
                    group_count1[group_id] += 1
                else:
                    group_count0[group_id] += 1
        flips = 0
        delta_cnt = defaultdict(lambda : 0)
        count_11 = 0
        for group_id in group_size:
            group_sz = group_size[group_id]
            n0 = group_count0[group_id]
            n1 = group_count1[group_id]
            if(group_sz == 1):
                # possible when there are both odd rows and odd columns
                if(n1 == 1):
                    delta_cnt[0] += n1
                    delta_cnt[1] += -n1
                    flips += n1
                pass
            elif(group_sz == 2):
                # possible when there are odd rows or odd columns 
                # no need to flip when all are same
                if(n0 == 2 or n1 == 2):
                    continue
                if(n0<n1):
                    delta_cnt[1] += n0
                    delta_cnt[0] += -n0
                    flips += n0
                elif(n0>n1):
                    delta_cnt[0] += n1
                    delta_cnt[1] += -n1
                    flips += n1
                else:
                    # this situation is dicey, we keep track of count of such cases in another variable
                    
                    delta_cnt[0] += -1
                    delta_cnt[1] += -1
                    count_11 +=1
                    flips += 1 # we will definitedly have to flip either 0 or 1 
                pass
            elif(group_sz == 3):
                # not possible
                pass
            elif(group_sz == 4):
                # not need to flip when all are same 
                if(n1 == 4 or n0 == 4 ):
                    continue
                # flip optimal
                if(n0<n1):
                    delta_cnt[1] += n0
                    delta_cnt[0] += -n0
                    flips += n0
                else:
                    delta_cnt[0] += n1
                    delta_cnt[1] += -n1
                    flips += n1
                pass
        rem_count1 = (cnt[1] + delta_cnt[1]) %4
        print(rem_count1)
        if(rem_count1 == 2):
            """
            it could have only come 
            - from middle row ( there are odd number of rows) 
            - from middle col ( there are odd number of cols)

            Cases :
            There are only groups of size two of the form 
            (1) (n0 =2, n1= 0) - flip two 0s --> (n0 =0, n1= 2)
            (2) (n0 =0, n1= 2) - flip two 1s --> (n0 =2, n1= 0)
            (3) (n0 =1, n1= 1) - dicey case 
                (a) there odd number of such groups
                    -> For one group we flip 0 -> 1
                    For remaining we flip 1 -> 0.
                    In total we get two new 1s.
                (b) there even number of such groups
                    -> For all groups we flip  1 -> 0 . 
                    In total the number of 1s doesnt changes
                    We need to pick a group from case - (1) or case - (2) and flip two  0s or 1s respectively
            In both of the above cases we need two additional flips
            """
            # case 3 - a
            if(count_11 >= 1):
                pass
            else:
                flips += 2
        return flips 
                
        
        
80900