题目描述
请你实现一个类 SubrectangleQueries
,它的构造函数的参数是一个 rows x cols
的矩形(这里用整数矩阵表示),并支持以下两种操作:
-
updateSubrectangle(int row1, int col1, int row2, int col2, int newValue)
用newValue
更新以(row1,col1)
为左上角且以(row2,col2)
为右下角的子矩形。 -
getValue(int row, int col)
返回矩形中坐标(row,col)
的当前值。
样例
输入:
[
"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]
]
输出:
[null,1,null,5,5,null,10,5]
解释:
SubrectangleQueries subrectangleQueries =
new SubrectangleQueries([[1,2,1],[4,3,4],[3,2,1],[1,1,1]]);
// 初始的 (4x3) 矩形如下:
// 1 2 1
// 4 3 4
// 3 2 1
// 1 1 1
subrectangleQueries.getValue(0, 2); // 返回 1
subrectangleQueries.updateSubrectangle(0, 0, 3, 2, 5);
// 此次更新后矩形变为:
// 5 5 5
// 5 5 5
// 5 5 5
// 5 5 5
subrectangleQueries.getValue(0, 2); // 返回 5
subrectangleQueries.getValue(3, 1); // 返回 5
subrectangleQueries.updateSubrectangle(3, 0, 3, 2, 10);
// 此次更新后矩形变为:
// 5 5 5
// 5 5 5
// 5 5 5
// 10 10 10
subrectangleQueries.getValue(3, 1); // 返回 10
subrectangleQueries.getValue(0, 2); // 返回 5
输入:
[
"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]
]
输出:
[null,1,null,100,100,null,20]
解释:
SubrectangleQueries subrectangleQueries =
new SubrectangleQueries([[1,1,1],[2,2,2],[3,3,3]]);
subrectangleQueries.getValue(0, 0); // 返回 1
subrectangleQueries.updateSubrectangle(0, 0, 2, 2, 100);
subrectangleQueries.getValue(0, 0); // 返回 100
subrectangleQueries.getValue(2, 2); // 返回 100
subrectangleQueries.updateSubrectangle(1, 1, 2, 2, 20);
subrectangleQueries.getValue(2, 2); // 返回 20
限制
- 最多有
500
次updateSubrectangle
和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
算法
(暴力枚举) 初始 $O(rc)$;修改 $O(1)$;查询 $O(Q)$
- 初始时,拷贝一份原数组。
- 修改时,记录下每次的修改内容。
- 查询时,倒序遍历历史的修改记录,如果有匹配的修改记录,则直接返回修改的值。否则,返回原数组中的值。
时间复杂度
- 初始时,需要 $O(rc)$ 的时间。
- 修改时,仅需要记录修改内容,故需要常数的时间。
- 查询时,需要遍历历史的修改记录,假设有 $Q$ 个记录,则需要 $O(Q)$ 的时间。
空间复杂度
- 需要额外 $O(rc + Q)$ 的空间存储原数组和历史的修改记录。
C++ 代码
class SubrectangleQueries {
public:
vector<vector<int>> r;
vector<vector<int>> updates;
SubrectangleQueries(vector<vector<int>>& rectangle) {
r = rectangle;
}
void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
updates.push_back({row1, col1, row2, col2, newValue});
}
int getValue(int row, int col) {
for (int i = updates.size() - 1; i >= 0; i--)
if (updates[i][0] <= row && row <= updates[i][2]
&& updates[i][1] <= col && col <= updates[i][3])
return updates[i][4];
return r[row][col];
}
};
/**
* Your SubrectangleQueries object will be instantiated and called as such:
* SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
* obj->updateSubrectangle(row1,col1,row2,col2,newValue);
* int param_2 = obj->getValue(row,col);
*/