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: MEDIUM
Tags: Matrices

Data structures
Skill types: Data structures

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]


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]


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]


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 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]


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]


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

	def getValue(self, row: int, col: int) -> int:
		return self.rectangle[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
		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]


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]


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]


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]


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.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]


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]


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]


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


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]


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]


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]


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]