本题利用的思想和一维差分/前缀和类似。
首先构造原数组的差分数组a:a[i][j] = s[i][j] - s[i - 1][j] - s[i][j - 1] + s[i - 1][j - 1];
然后通过修改差分数组达到改变前缀和数组的目的。
始终要记得,s数组是a数组的前缀和数组,比如对a数组的a[i][j]的修改,会影响到s数组中从s[i][j]及往后的每一个数。
a[x1][ y1 ] +=c ; 让整个s数组中蓝色矩形面积的元素都加上了c。
a[x1,][y2+1]-=c ; 让整个s数组中绿色矩形面积的元素再减去c,使其内元素不发生改变。
a[x2+1][y1]- =c ; 让整个s数组中紫色矩形面积的元素再减去c,使其内元素不发生改变。
a[x2+1][y2+1]+=c; 让整个s数组中红色矩形面积的元素再加上c,红色内的相当于被减了两次,再加上一次c,才能使其恢复。
修改a数组后,重新循环构造新的前缀和数组,此时这个前缀和数组s就是我们想要的答案。
#include<iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], s[N][N];
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", &s[i][j]);
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
a[i][j] = s[i][j] - s[i - 1][j] - s[i][j - 1] + s[i - 1][j - 1];//构造差分数组
while (q -- )
{
int x1, y1, x2, y2, c;
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
a[x1][y1] += c;//通过改变差分数组来修改前缀和数组
a[x1][y2 + 1] -= c;
a[x2 + 1][y1] -= c;
a[x2 + 1][y2 + 1] += c;
}
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
s[i][j] = a[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];//重新构造前缀和数组
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ ) printf("%d ", s[i][j]);
printf("\n");
}
return 0;
}