同一维差分法的思想,
a[i][j]数组是b[i][j]数组的前缀和数组,即,b[i][j]是a[i][j]的差分数组。
已知原数组a中被选中的子矩阵以(x1, y1)为左上角,以(x2, y2)为右上角所围成的矩形区域。
这里始终要记得,a数组是b数组的前缀和数组,比如对b数组的b[i][j]修改,会影响到a数组中从a[i][j]及往后的每一个数。
假定我们已经构造好了b数组,类比一维的差分,我们执行以下操作来使被选中的子矩阵中的每一个元素的值都加上c。
b[x1][y1] = b[x1][y1] + c;
b[x1][y2 + 1] = b[x1][y2 + 1] - c;
b[x2 + 1][y1] = b[x2 + 1][y1] - c;
b[x2 + 1][y2 + 1] + c;
更形象地,我们画图来进行相关描述:
b[x1][y1] += c; 对应上图1中的蓝色矩形中覆盖的元素都加上了c。
b[x1][y2 + 1] -= c; 对应上图2中绿色矩形中覆盖的元素都减掉c。
b[x2 + 1][y1] -= c; 对应上图3中绿色矩形中覆盖的元素都减掉c。
b[x2 + 1][y2 + 1] += c; 对应上图4中红色矩形中覆盖的元素都加上c。
我们可以进一步将上述操作封装成一个插入函数:
void insert(int x1, int y1, int x2, int y2, int c)
{
// 对数组执行插入操作,等价于对a数组中的(x1, y1)到(x2, y2)之间的元素都加上c
b[x1][y1] += c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y1] -= c;
b[x2 + 1][y2 + 1] += c;
}
构建差分数组
假定数组a的所有元素都为空,此时数组b的所有元素也都为空。但实际上数组a不是空的,我们每次让以(i, j)为左上角到以(i, j)为右下角的矩形区域内的元素(实际上即为元素a[i][j]),去插入c=a[i][j],这种插入的操作配合上面的插入函数也会进一步影响到b数组,因此b数组就可以求出来。
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m ;j++)
{
insert(i, j, i, j, a[i][j]);
}
}