类似差分的概念,差分矩阵我们的定义两个矩阵
A
与
B
A与B
A与B,其中对于A矩阵的每个元素
a
i
j
a_{ij}
aij,我们有
a
i
j
=
∑
m
=
1
i
∑
n
=
1
j
b
m
n
a_{ij}=\sum^i_{m=1}\sum^j_{n=1}b_{mn}
aij=m=1∑in=1∑jbmn
如图中的黄色部分元素之和。
问题与我们能在上一篇博客中的相同,即如何利用算法,通过对B矩阵的元素进行操作从而简化对A矩阵的操作。在这里我们设想加入B矩阵的元素
b
i
j
b_{ij}
bij加上了某个常数c,此时A矩阵中的元素会发生什么?
我们通过公式观察到只有位于
(
i
,
j
)
(i,j)
(i,j)位置右下角的A矩阵的元素会受到这个操作的影响,因为只有当
x
>
i
,
y
>
j
x>i,y>j
x>i,y>j的元素
a
x
y
a_{xy}
axy在计算时使用到了
b
i
j
b_{ij}
bij这个加上了常数c的元素,所以我们得到结论:当
b
i
j
b_{ij}
bij加上常数c,与此对应的,
a
x
y
(
x
>
i
,
y
>
j
)
a_{xy}(x>i,y>j)
axy(x>i,y>j)的元素全部加上了常数c。
当我们最终的目的是对A中某个子矩阵中的元素进行加上常数c的操作。
图中黄色部分为我们希望操作的部分,由上面得到的结论,我们有
b
x
1
,
y
1
+
=
c
,
对应图中红色字体的“
+
c
"
b_{x_1,y_1}+=c,对应图中红色字体的“+c"
bx1,y1+=c,对应图中红色字体的“+c"
b
x
2
+
1
,
y
1
−
=
c
,
对图中黑色字体的
"
−
c
"
b_{x_2+1,y_1}-=c,对图中黑色字体的"-c"
bx2+1,y1−=c,对图中黑色字体的"−c"
b
x
1
,
y
2
+
1
−
=
c
,
对应图中绿色字体的
"
−
c
"
b_{x_1,y_2+1}-=c,对应图中绿色字体的"-c"
bx1,y2+1−=c,对应图中绿色字体的"−c"
b
x
x
2
+
1
,
y
y
2
+
1
+
=
c
,对应图中粉色字体的
"
+
c
"
b_{x_{x_2+1},y_{y_2+1}}+=c,对应图中粉色字体的"+c"
bxx2+1,yy2+1+=c,对应图中粉色字体的"+c"
代码
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], b[N][N];
void insert(int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;
}
int main()
{
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
insert(i, j, i, j, a[i][j]);
while (q--)
{
int x1, y1, x2, y2, c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1, y1, x2, y2, c);
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++) printf("%d ", b[i][j]);
puts("");
}
return 0;
}