Implement the class SubrectangleQueries which receives a rows x cols rectangle as a matrix of integers in the constructor and supports two methods:
1. updateSubrectangle(int row1, int col1, int row2, int col2, int newValue)

Updates all values with newValue in the subrectangle whose upper left coordinate is (row1,col1) and bottom right coordinate is (row2,col2).

2. getValue(int row, int col)

Returns the current value of the coordinate (row,col) from the rectangle.

 
Example 1:
Input
["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue","getValue"]
[[[[1,2,1],[4,3,4],[3,2,1],[1,1,1]]],[0,2],[0,0,3,2,5],[0,2],[3,1],[3,0,3,2,10],[3,1],[0,2]]
Output
[null,1,null,5,5,null,10,5]
Explanation
SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,2,1],[4,3,4],[3,2,1],[1,1,1]]);  
// The initial rectangle (4x3) looks like:
// 1 2 1
// 4 3 4
// 3 2 1
// 1 1 1
subrectangleQueries.getValue(0, 2); // return 1
subrectangleQueries.updateSubrectangle(0, 0, 3, 2, 5);
// After this update the rectangle looks like:
// 5 5 5
// 5 5 5
// 5 5 5
// 5 5 5 
subrectangleQueries.getValue(0, 2); // return 5
subrectangleQueries.getValue(3, 1); // return 5
subrectangleQueries.updateSubrectangle(3, 0, 3, 2, 10);
// After this update the rectangle looks like:
// 5   5   5
// 5   5   5
// 5   5   5
// 10  10  10 
subrectangleQueries.getValue(3, 1); // return 10
subrectangleQueries.getValue(0, 2); // return 5

Example 2:
Input
["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue"]
[[[[1,1,1],[2,2,2],[3,3,3]]],[0,0],[0,0,2,2,100],[0,0],[2,2],[1,1,2,2,20],[2,2]]
Output
[null,1,null,100,100,null,20]
Explanation
SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,1,1],[2,2,2],[3,3,3]]);
subrectangleQueries.getValue(0, 0); // return 1
subrectangleQueries.updateSubrectangle(0, 0, 2, 2, 100);
subrectangleQueries.getValue(0, 0); // return 100
subrectangleQueries.getValue(2, 2); // return 100
subrectangleQueries.updateSubrectangle(1, 1, 2, 2, 20);
subrectangleQueries.getValue(2, 2); // return 20

 
Constraints:

There will be at most 500 operations considering both methods: updateSubrectangle and getValue.
1 <= rows, cols <= 100
rows == rectangle.length
cols == rectangle[i].length
0 <= row1 <= row2 < rows
0 <= col1 <= col2 < cols
1 <= newValue, rectangle[i][j] <= 10^9
0 <= row < rows
0 <= col < cols

Difficulty: interview

Starter code:

class SubrectangleQueries:
    def __init__(self, rectangle: List[List[int]]):
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
    def getValue(self, row: int, col: int) -> int:
# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)

Solutions:
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.initial_rectangle = rectangle
        self.rectangles = []
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.rectangles.append((row1, col1, row2, col2, newValue))
        

    def getValue(self, row: int, col: int) -> int:
        for row1, col1, row2, col2, value in reversed(self.rectangles):
            if row1 <= row <= row2 and col1 <= col <= col2:
                return value
        return self.initial_rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self._rect = rectangle
        self._instrs = []

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self._instrs.append([row1, row2, col1, col2, newValue])
        

    def getValue(self, row: int, col: int) -> int:
        for row1, row2, col1, col2, val in self._instrs[::-1]:
            if row1 <= row and row <= row2 and col1 <= col and col<= col2:
                return val
        return self._rect[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:
    rectangle = [[]]

    def __init__(self, rectangle):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        while(row1 <= row2):
            self.rectangle[row1][col1:col2+1] = [newValue] * len(self.rectangle[row1][col1:col2+1])
            row1 += 1


    def getValue(self, row: int, col: int) -> int:
        return (self.rectangle[row][col])


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        # first pass solution
        for row in self.rectangle[row1:row2+1]:
            for i in range(col1, col2+1):
                row[i] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.matrix = rectangle
        self.update = []
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.update.append((row1, col1, row2, col2, newValue))
        

    def getValue(self, row: int, col: int) -> int:
        ans = None
        for i in range(len(self.update) - 1, -1, -1):
            row1, col1, row2, col2, val = self.update[i]
            if row1 <= row <= row2 and col1<= col <= col2:
                ans = val
                break
        return ans if ans else self.matrix[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rec = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        rec = self.rec
        col_range = col1+col2-col1+1
        for i in range(row2-row1+1):
            recrow = rec[row1+i]
            for j in range(col1, col_range):
                recrow[j] = newValue


    def getValue(self, row: int, col: int) -> int:
        return self.rec[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.grid = rectangle
        # make a new dictionary
        self.rec = {}
\t\t# with enumerate we can iterate through the list rectangle, 
\t\t# taking each row and its index
        for i, row in enumerate(rectangle):
\t\t\t# we map each row to its index as it`s more space-efficent
            self.rec[i] = row
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        # start = (row1, col1)
        # end = (row2, col2)
        # diffr = row2 - row1
        # diffc = col2 - col1
        
        # self.grid[row1][col1] = newValue
        
        # for r in range(diffr+1):
        #     for c in range(diffc+1):
        #         self.grid[row1+r][col1+c] = newValue
        # for i in range(row1, row2+1):
        #     self.grid[i] = self.grid[i][:col1] + [newValue]*(col2-col1+1) + self.grid[col2+1:]
        for i in range(row1, row2+1):
\t\t\t# we put new value only from col1 to col2, but we leave other columns as is
            self.rec[i] = self.rec[i][:col1] + [newValue]*(col2-col1+1) + self.rec[i][col2+1:]

    def getValue(self, row: int, col: int) -> int:
        # return self.grid[row][col]
        return self.rec[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)

import numpy as np
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = np.array(rectangle)

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.rectangle[row1:row2+1,col1:col2+1] = newValue
        #for i in range(row1,row2+1):
            #for j in range(col1,col2+1):
                #self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.q = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2 + 1):
            for col in range(col1, col2 + 1):
                self.q[row][col] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.q[row][col] 


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.q = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2 + 1):
            for col in range(col1, col2 + 1):
                self.q[row][col] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.q[row][col] 

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
\t\t# make a new dictionary
        self.rec = {}
\t\t# with enumerate we can iterate through the list rectangle, 
\t\t# taking each row and its index
        for i, row in enumerate(rectangle):
\t\t\t# we map each row to its index as it`s more space-efficent
            self.rec[i] = row
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
\t\t# we want to put new value from row1 to row2, so we iterate through them
        for i in range(row1, row2+1):
\t\t\t# we put new value only from col1 to col2, but we leave other columns as is
            self.rec[i] = self.rec[i][:col1] + [newValue]*(col2-col1+1) + self.rec[i][col2+1:]

    def getValue(self, row: int, col: int) -> int:
\t\t# take row (of type list) from dictionary rec, take specified col from row
        return self.rec[row][col]

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rect[i][j]=newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rect[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        self.changes = []

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.changes.append((row1, col1, row2, col2, newValue))

    def getValue(self, row: int, col: int) -> int:
        for row1, col1, row2, col2, newValue in reversed(self.changes):
            if row1 <= row <= row2 and col1 <= col <= col2:
                return newValue
        return self.rectangle[row][col]

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect=  rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rect[i][j] = newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rect[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        return
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:        
        for i in range(row1, row2 + 1):
            for j in range(col1, col2 + 1):
                self.rectangle[i][j] = newValue
        return
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2 + 1):
            for j in range(col1, col2 + 1):
                self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


# How do I handle input that is out of bounds of the rectangle?
# Can the new value be negative or 0?
# Give the same row values and col values
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        self.rectangles = []
        
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range((row2-row1+1)):
            for j in range(col2-col1+1):
                self.rectangle[row1+i][col1+j]= newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.grid = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        start = (row1, col1)
        end = (row2, col2)
        diffr = row2 - row1
        diffc = col2 - col1
        
        # self.grid[row1][col1] = newValue
        
        for r in range(diffr+1):
            for c in range(diffc+1):
                self.grid[row1+r][col1+c] = newValue
        
        

    def getValue(self, row: int, col: int) -> int:
        return self.grid[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle= rectangle
        
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range((row2-row1+1)):
            for j in range(col2-col1+1):
                self.rectangle[row1+i][col1+j]= newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        m,n = len(rectangle), len(rectangle[0])
        self.mat = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2 + 1):
            for j in range(col1, col2 + 1):
                self.mat[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.mat[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect = rectangle
        self.patches = []

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.patches.append((row1,col1,row2,col2,newValue))
        
    def matchesPatch(self, row, col, patch):
        return patch[0] <= row and row <= patch[2] and patch[1] <= col and col <= patch[3]

    def getValue(self, row: int, col: int) -> int:
        for patch in reversed(self.patches):
            if self.matchesPatch(row, col, patch):
                return patch[-1]
        return self.rect[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = copy.deepcopy(rectangle)
        
        # Thanks for sharing. Just one observation: it's better and safer to deepcopy the rectangle in __init__ to prevent self.rectangle and rectangle from sharing the same memory. otherwise, changing rectangle, would change self.rectangle (object's rectangle) as they share same memory. Also passing the same rectangle to separate objects (in __init__) would mean they all share the same memory which is not what we would want. As such __init__ should change to:
        # self.rectangle = copy.deepcopy(rectangle)
        
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries(object):

    def __init__(self, rectangle):
        self.rectangle = copy.deepcopy(rectangle)

    def updateSubrectangle(self, row1, col1, row2, col2, newValue):
        for i in range(row1, row2 + 1):
            for j in range(col1, col2 + 1):
                self.rectangle[i][j] = newValue
        return self.rectangle

    def getValue(self, row, col):
        return self.rectangle[row][col]

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for r in range(row1, row2+1):
            for c in range(col1, col2+1):
                self.rectangle[r][c] = newValue
            
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row2 - row1 + 1):
            for j in range(col2 - col1 + 1):
                self.rectangle[row1 + i][col1 + j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


import numpy as np
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        for i in rectangle:
            print(i)
        print(\"\
\")
        self.rectangle = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        rec =self.rectangle
        
        for i in range(row1, row2 + 1):
            row = []
            for j in range(col1, col2 + 1):
                rec[i][j] = newValue
                row.append(rec[i][j])
            

            
        
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)

import numpy as np 
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]




class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        
        for row in range(row1, row2 + 1) : 
            for column in range(col1, col2 + 1) : 
                self.rectangle[row][column] = newValue 
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.r = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for x in range(row1, row2+1):
            for y in range(col1, col2+1):
                self.r[x][y] = newValue
                
        return None

    def getValue(self, row: int, col: int) -> int:
        return self.r[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.orig = rectangle
        self.updates =  []

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.updates.append((row1, col1, row2, col2, newValue))

    def getValue(self, row: int, col: int) -> int:
        for a, b,  c, d, v in reversed(self.updates):
            if a <= row <= c and b <= col <= d:
                return v
        return self.orig[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.columns = len(rectangle[0])
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        initial = col1
        while row1 <= row2 and col1 <= col2:
            self.rectangle[row1][col1] = newValue
            col1 += 1

            if not col1 < self.columns or not col1 <= col2:
                col1 = initial
                row1 += 1

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
    


import numpy as np

class SubrectangleQueries:

    
    
    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:        
        for i in range(row2+1-row1):
            for j in range(col2+1-col1):                
                self.rectangle[row1+i][col1+j] = newValue               

    def getValue(self, row: int, col: int) -> int:             
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


import numpy as np 

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = np.asarray(rectangle)
        
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.rectangle[row1:row2+1, col1:col2+1] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row, col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2+1):
            for col in range(col1, col2+1):
                self.rect[row][col] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rect[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.x=rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        i=row1
        j=col1
        while i<row2+1 and j<col2+1:
            self.x[i][j]=newValue
            if j==col2:
                j=col1
                i=i+1
            else:
                j=j+1      
            
        

    def getValue(self, row: int, col: int) -> int:
        return self.x[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries(object):

    def __init__(self, rectangle):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1, col1, row2, col2, newValue):
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue
\t\t\t\t
    def getValue(self, row, col):
        return self.rectangle[row][col]


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle=rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2+1):
            for col in range(col1, col2+1):
                self.rectangle[row][col] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rectangle[i][j] = newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self. rec=rectangle
        # for i in range(len(self.rectangle)):
        #     a=[]
        #     for j in range(len(self.rectangle[i])):
        #         a.append(self.rectangle[i][j])
        #     rec.append(a)

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, (row2+1)):
            for j in range(col1, (col2+1)):
                self.rec[i][j]=newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rec[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle=rectangle
        


    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rectangle[i][j]=newValue
                
        
    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle=rectangle
        self.pos=[]
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.pos.append([row1,col1,row2,col2,newValue])
        
        

    def getValue(self, row: int, col: int) -> int:
        if(len(self.pos)==0):
            return self.rectangle[row][col]
        else:
            t=-1
            for p in self.pos:
                row1,col1,row2,col2,val=p
                if((row>=row1 and row<=row2) and (col>=col1 and col<=col2)):
                    t=val
        if(t==-1):
            return self.rectangle[row][col]
        return t
                    
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.r = rectangle 

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2 + 1):
            for j in range(col1, col2 + 1):
                self.r[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.r[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.r = [[col for col in row] for row in rectangle]
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.r[i][j] = newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.r[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(len(self.rectangle)):
            if not row1 <= row <= row2:
                continue
            for col in range(len(self.rectangle[row])):
                if not col1 <= col <= col2:
                    continue
                self.rectangle[row][col] = newValue


    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue
    
    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


import numpy as np

class SubrectangleQueries:
    def __init__(self, rectangle: List[List[int]]):
        self.matrix = np.array(rectangle)
        
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.matrix[row1:row2+1, col1:col2+1] = newValue
        
    def getValue(self, row: int, col: int) -> int:
        return self.matrix[row, col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        print((self.rectangle))

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        # index into rectangle and change all values in subrectangle
        # gonna have to loop through it
        for row in range(len(self.rectangle)):
            if row >= row1 and row <= row2:
                for col in range(len(self.rectangle[0])):
                    if col >= col1 and col <= col2:
                        self.rectangle[row][col] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2+1):
            for col in range(col1, col2+1):
                self.rectangle[row][col] = newValue
        
    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rectangle[i][j] = newValue
        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle=rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1,row2+1):
            for j in range(col1,col2+1):
                self.rectangle[i][j]=newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.r = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2 + 1):
            self.r[i][col1:col2+1] = [newValue] * (col2 - col1 + 1)

    def getValue(self, row: int, col: int) -> int:
        return self.r[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


\"\"\"
class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self._rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2 + 1):
            self._rectangle[row][col1:col2+1] = [newValue] * (col2 - col1 + 1)

    def getValue(self, row: int, col: int) -> int:
        return self._rectangle[row][col]
\"\"\"        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
\t\t# make a new dictionary
        self.rec = {}
\t\t# with enumerate we can iterate through the list rectangle, 
\t\t# taking each row and its index
        for i, row in enumerate(rectangle):
\t\t\t# we map each row to its index as it`s more space-efficent
            self.rec[i] = row
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
\t\t# we want to put new value from row1 to row2, so we iterate through them
        for i in range(row1, row2+1):
\t\t\t# we put new value only from col1 to col2, but we leave other columns as is
            self.rec[i] = self.rec[i][:col1] + [newValue]*(col2-col1+1) + self.rec[i][col2+1:]

    def getValue(self, row: int, col: int) -> int:
\t\t# take row (of type list) from dictionary rec, take specified col from row
        return self.rec[row][col]

class SubrectangleQueries:
    rect=[]
    
    def __init__(self, rectangle: List[List[int]]):
        r = len(rectangle)
        c = len(rectangle[0])
        self.rect = [[0 for i in range(c)] for j in range(r)]
        for i in range(r):
            for j in range(c):
                self.rect[i][j]=rectangle[i][j]
        
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        r=row2-row1
        c=col2-col1
        for i in range(row1,row1+r+1):
            for j in range(col1,col1+c+1):
                self.rect[i][j]=newValue
                
    def getValue(self, row: int, col: int) -> int:
        return self.rect[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        # time complexity O(n)
        # space complexity O(1) since it's re-using the input matrix
        for i in range(row1, row2+1):
            for j in range(col1, col2+1):
                self.rect[i][j] = newValue
        
    def getValue(self, row: int, col: int) -> int:
        return self.rect[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for i in range(row1, row2+1):
            for k in range(col1, col2+1):
                self.rectangle[i][k] = newValue

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


import itertools

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.w = len(rectangle[0])
        self.rectangle = list(itertools.chain.from_iterable(rectangle))
        

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        start, end = col1 + row1 * self.w, col2 + row2 * self.w
        for i in range(col1,col2 + 1):
            for j in range(row1, row2 + 1):
                self.rectangle[i + j * self.w] = newValue

        

    def getValue(self, row: int, col: int) -> int:
        return self.rectangle[col + row * self.w]
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.R = rectangle

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1,row2+1):
            self.R[row][col1:col2+1] = [newValue]*(col2-col1+1)
        return None
    
    def getValue(self, row: int, col: int) -> int:
        return self.R[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rect = rectangle
        self.height = len(self.rect)
        self.width = len(self.rect[0])

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        for row in range(row1, row2 + 1):
            self.rect[row][col1:col2+1] = [newValue] * (col2 - col1 + 1)
        

    def getValue(self, row: int, col: int) -> int:
        if row > self.height - 1 or col > self.width - 1:
            return None
        return self.rect[row][col]
        
        


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)


class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        
        self.rows=len(rectangle)
        self.rectangle=rectangle
        if self.rows!=0:
              self.cols=len(rectangle[0])
        else:
             self.cols=0
                
                
    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        if row2>=row1 and col1<=col2 and row2<self.rows:
                        for i in range(row1,row2+1):
                                self.rectangle[i][col1:(col2+1)]=[newValue]*(col2-col1+1)
        else:
            print(\"Input Wrong\")
                
    def getValue(self, row: int, col: int) -> int:
        if row<self.rows and col<self.cols:
                row_select= self.rectangle[row]
                return(row_select[col])
        else:
            print(\"Input Wrong\") 


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)