差分矩阵(二维差分)
一、算法描述
上一篇文章介绍了一维差分,本篇文章来介绍一下什么是二维差分。
含义
- 显然一维差分是一维前缀和的原数组,那么二维差分就是二维前缀和的原数组。
怎么求
- 跟一维一样,插入一遍即可,但是要注意每次插入要在同一个位置内插入,
insert(i, j, i, j, a[i][j]);
。
怎么用
-
一维差分是使得数组 \(a[n]\) 在 \([l, r]\) 范围内的数都加上 \(c\) ,那么二维差分的作用就是使得 \(a[n][n]\) 在 \((x1, y1)\) 到 \((x2, y2)\) 范围内的数都加上 \(c\) 。
-
差分操作的都是原数组 \(b\) ,通过 \(b\) 求一遍前缀和才能得到 \(a\) ,也要注意我们操作的都是差分数组 \(b\) ,那么我们如何操作 \(b\) 才能得到上面的效果呢?
-
首先
b[x1][y1] += c;
,这样就会使得 \((x1, y1)\) 到右下角所有的数都加上 \(c\) ,然后有一些是不需要加但是加了的,所以要减回来,b[x2 + 1][y1] -= c, b[x1][y2 + 1] -= c;
,这样操作之后右下角有一块减了两次,所以还要再加回来一次,b[x2 + 1][y2 + 1] += c;
,这样就可以达到效果了,建议读者在草稿纸上画一下,更好理解。
代码如下:
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;
}
二、题目描述
输入一个 \(n\) 行 \(m\) 列的整数矩阵,再输入 \(q\) 个操作,每个操作包含五个整数 \(x1, y1, x2, y2, c\),其中 \((x1,y1)\) 和 \((x2,y2)\) 表示一个子矩阵的左上角坐标和右下角坐标。
每个操作都要将选中的子矩阵中的每个元素的值加上 \(c\)。
请你将进行完所有操作后的矩阵输出。
输入格式
第一行包含整数 \(n, m, q\)。
接下来 \(n\) 行,每行包含 \(m\) 个整数,表示整数矩阵。
接下来 \(q\) 行,每行包含 \(5\) 个整数 \(x1,y1,x2,y2,c\),表示一个操作。
输出格式
共 \(n\) 行,每行 \(m\) 个整数,表示所有操作进行完毕后的最终矩阵。
数据范围
\(1≤n,m≤1000,\)
\(1≤q≤100000,\)
\(1≤x1≤x2≤n,\)
\(1≤y1≤y2≤m,\)
\(−1000≤c≤1000,\)
\(−1000≤矩阵内元素的值≤1000\)
输入样例:
3 4 3
1 2 2 1
3 2 2 1
1 1 1 1
1 1 2 2 1
1 3 2 3 2
3 1 3 4 1
输出样例:
2 3 4 1
4 3 4 1
2 2 2 2
三、题目来源
四、源代码
#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()
{
cin >> n >> m >> q;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> 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)
a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + b[i][j];
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= m; ++j) cout << a[i][j] << ' ';
cout << endl;
}
return 0;
}