class Solution:
    def hitBricks(self, grid: List[List[int]], hits: List[List[int]]) -> List[int]:
        """ tc O(R*C + H) , H is len of hits. 
        
        """
        
        r = len(grid)
        c = len(grid[0])
        
        # 1. set connected grid to 2, and 2. remember connected value 
        def dfs(i,j):
            #(1) grid[i][j] == 1:  set to 2, within valid bound, accumutive sum,  (2) grid[i][j] != 1   => return 0 
            if grid[i][j] == 1:
                grid[i][j] = 2
                res = 1
                for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]:
                    if 0<= x < r and 0 <= y < c and grid[x][y] == 1:
                        res += dfs(x,y)
                return res
            return 0
            
            
        #check current pos connected to ceiling/ no-failing
        def is_connected(i,j):
            # (1) (i,j) is ceiling. (2) (i,j) neighbour grid value == 2 
            return i == 0 or any([0<= x < r and 0 <= y < c and  grid[x][y] == 2 for x,y in [(i+1,j),(i-1,j),(i,j+1),(i,j-1)]])
            
        # step1: remove hit  
        for h in hits:
            grid[h[0]][h[1]] -= 1 
        
        # step2: connect ceil 
        for i in range(c):
            dfs(0,i)
        
        # step3: reversely put back hit, do dfs, update res 
        res = [0] * len(hits)
        for k in range(len(hits)-1,-1,-1):
            x,y = hits[k][0],hits[k][1]
            grid[x][y]  +=  1
            if grid[x][y] == 1 and is_connected(x,y):
                res[k] = dfs(x,y) -1 
        return res 

refer [TODO]

class UF:
    def __init__(self,n):
        self.p = list(range(n))
        self.rank = [1] * n
        
    def find(self,u):
        if u != self.p[u]:
            self.p[u] = self.find(self.p[u])
        return self.p[u]
    
    def union(self,u,v):
        pv,pu = self.find(v), self.find(u)
        if pv == pu:
            return True 
        elif self.rank[pv] >= self.rank[pu]:
            self.p[pu] = self.pv
            self.rank[pv] += self.rank[pu]
        else:
            self.p[pv] = self.pu
            self.rank[pu] += self.rank[pv]
        return False
        
        
class Solution:
    def hitBricks(self, grid: List[List[int]], hits: List[List[int]]) -> List[int]:
        r = len(grid)
        c = len(grid[0])
        # init UF
        uf = UF(r*c)
        for i in range(1,c):
            if grid[0][c] == 1 and grid[0][c-1] == 1: 
                union(c,c-1)
        
        # union bricks below
        
        
        # loop through hits checki its left,right, down , if they only connected with current hit, if yes, set neighbour's parent into itself and neighbour value ==0  cnt += 1 
        # each hit after it expand the sourroundings, append cnt into res