解题思路
-
问题分析:
- 需要对矩阵进行多次子矩阵区域修改
- 直接修改会导致时间复杂度
- 可以使用二维差分数组优化到
-
二维差分数组优化:
- 对于区域 加上 ,需要:
- 最后通过二维前缀和还原原矩阵
- 对于区域 加上 ,需要:
-
实现要点:
- 差分数组需要多开一行一列
- 注意数据范围,使用 类型
- 注意下标从 开始
代码
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n, m, q;
cin >> n >> m >> q;
// 读入原矩阵
vector<vector<long long>> a(n + 2, vector<long long>(m + 2, 0));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> a[i][j];
}
}
// 构建二维差分数组
vector<vector<long long>> diff(n + 2, vector<long long>(m + 2, 0));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
// 二维差分
diff[i][j] += a[i][j];
diff[i][j+1] -= a[i][j];
diff[i+1][j] -= a[i][j];
diff[i+1][j+1] += a[i][j];
}
}
// 处理修改操作
while(q--) {
int x1, y1, x2, y2;
long long k;
cin >> x1 >> y1 >> x2 >> y2 >> k;
// 二维差分修改
diff[x1][y1] += k;
diff[x1][y2+1] -= k;
diff[x2+1][y1] -= k;
diff[x2+1][y2+1] += k;
}
// 还原矩阵并输出
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
// 二维前缀和还原
a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + diff[i][j];
cout << a[i][j] << (j == m ? '\n' : ' ');
}
}
return 0;
}
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
String[] line = br.readLine().split(" ");
int n = Integer.parseInt(line[0]);
int m = Integer.parseInt(line[1]);
int q = Integer.parseInt(line[2]);
// 读入原矩阵
long[][] a = new long[n + 2][m + 2];
for(int i = 1; i <= n; i++) {
line = br.readLine().split(" ");
for(int j = 1; j <= m; j++) {
a[i][j] = Long.parseLong(line[j-1]);
}
}
// 构建二维差分数组
long[][] diff = new long[n + 2][m + 2];
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
diff[i][j] += a[i][j];
diff[i][j+1] -= a[i][j];
diff[i+1][j] -= a[i][j];
diff[i+1][j+1] += a[i][j];
}
}
// 处理修改操作
while(q-- > 0) {
line = br.readLine().split(" ");
int x1 = Integer.parseInt(line[0]);
int y1 = Integer.parseInt(line[1]);
int x2 = Integer.parseInt(line[2]);
int y2 = Integer.parseInt(line[3]);
long k = Long.parseLong(line[4]);
diff[x1][y1] += k;
diff[x1][y2+1] -= k;
diff[x2+1][y1] -= k;
diff[x2+1][y2+1] += k;
}
// 还原矩阵并输出
StringBuilder sb = new StringBuilder();
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + diff[i][j];
sb.append(a[i][j]).append(j == m ? '\n' : ' ');
}
}
out.print(sb);
out.flush();
}
}
def main():
n, m, q = map(int, input().split())
# 读入原矩阵
a = [[0] * (m + 2) for _ in range(n + 2)]
for i in range(1, n + 1):
row = list(map(int, input().split()))
for j in range(1, m + 1):
a[i][j] = row[j-1]
# 构建二维差分数组
diff = [[0] * (m + 2) for _ in range(n + 2)]
for i in range(1, n + 1):
for j in range(1, m + 1):
diff[i][j] += a[i][j]
diff[i][j+1] -= a[i][j]
diff[i+1][j] -= a[i][j]
diff[i+1][j+1] += a[i][j]
# 处理修改操作
for _ in range(q):
x1, y1, x2, y2, k = map(int, input().split())
diff[x1][y1] += k
diff[x1][y2+1] -= k
diff[x2+1][y1] -= k
diff[x2+1][y2+1] += k
# 还原矩阵并输出
for i in range(1, n + 1):
for j in range(1, m + 1):
a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + diff[i][j]
print(a[i][j], end='\n' if j == m else ' ')
if __name__ == "__main__":
main()
算法及复杂度
- 算法:二维差分数组
- 时间复杂度:,其中 和 是矩阵的行数和列数, 是操作次数
- 空间复杂度:,用于存储差分数组