二维数组的差分
一、基本概念
二维数组差分是一种高效处理区间修改操作的数据结构技巧,常用于解决矩阵区域增减问题。
差分是前缀和的逆运算,对于二维数组,差分数组 diff[i][j] 表示原数组 a[i][j] 与 a[i-1][j] + a[i][j-1] - a[i-1][j-1] 的差值。
二维差分是处理子矩阵增减操作的高效方法。
原矩阵:
a[i][j](1 ≤ i ≤ m, 1 ≤ j ≤ n)差分矩阵:
b[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1]
二、核心性质
差分矩阵的前缀和就是原矩阵
子矩阵增减操作:
给以
(x1,y1)为左上角,(x2,y2)为右下角的子矩阵每个元素加c:
b[x1][y1] += c b[x2+1][y1] -= c b[x1][y2+1] -= c b[x2+1][y2+1] += c
因为差分数组的前缀和相当于原数组,所以对差分数组进行以上四个单点操作后,就相当于给原数组数组的区块加上一个值 c
(1)构建方式
//求出差分数组
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
b[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
}
}(2)增减操作
void add(int x1,int y1,int x2,int y2,int c)
{
b[x1][y1] += c; // 影响从(x1,y1)开始的所有区域
b[x2 + 1][y1] -= c; // 消除x方向超出范围的影响
b[x1][y2 + 1] -= c; // 消除y方向超出范围的影响
b[x2 + 1][y2 + 1] += c; // 补偿多减去的区域(容斥原理)
}(3)还原操作
b[i][j] += b[i-1][j] + b[i][j-1] - b[i-1][j-1];
四、参考代码
#include <iostream>
using namespace std;
int a[100][100]; // 原始数组
int b[100][100]; // 差分数组
int res[100][100]; // 结果数组
// 区域增加操作
void rangeAdd(int x1, int y1, int x2, int y2, int c) {
b[x1][y1] += c;
b[x1][y2+1] -= c;
b[x2+1][y1] -= c;
b[x2+1][y2+1] += c;
}
// 从差分数组还原原数组
void restoreArray(int m, int n) {
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
res[i][j] = res[i-1][j] + res[i][j-1] - res[i-1][j-1] + b[i][j];
}
}
}
int main() {
int m, n, c;
cin >> m >> n;
// 1. 先输入原始数组的值
cout << "请输入" << m << "行" << n << "列的矩阵:" << endl;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
}
// 2. 构建差分数组
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
b[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1];
}
}
// 3. 输入修改参数
cout << "请输入要增加的值c和区域(x1,y1)-(x2,y2):" << endl;
int a1, b1, a2, b2;
cin >> c >> a1 >> b1 >> a2 >> b2;
// 4. 执行区域增加操作
rangeAdd(a1, b1, a2, b2, c);
// 5. 还原数组
restoreArray(m, n);
// 6. 输出结果
cout << "修改后的数组:" << endl;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cout << res[i][j] << " ";
}
cout << endl;
}
return 0;
}扫描二维码推送至手机访问。
版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。


