一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
一维差分
概念
- 构造完成以后:a数组是b数组的前缀和
- b称为a的差分,a称为b的前缀和
- 假定a数组初始的时候全部都是0,然后在对应的区间加上对应的a[i]即可
作用
- 假设已经构造出来B数组了,如果想求A数组,则对B数组求一遍前缀和即可,
时间复杂度:O(n) - 给定一个区间[l, r],在A数组里面在[l, r]区间的所有元素都+c,如果循环来做,
时间复杂度O(n),但是用差分可以做到O(1),如果上面的这个操作完成以后,我们想求一下原来的A数组,用B数组来求一下前缀和(对B数组扫描一边)即可得到原来的A数组,时间复杂度:O(n)b[l] + c:a[l]~a[n]全部都加上c了,所以要打个补丁,b[r + 1] - c,这样就可以实现上面这个需求了
题目
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int a[N], b[N]; // a:原数组 b:差分数组
// 插入函数,a[l ~ r] + c
void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
// 1. 将原数组的每个数都插入进去
for (int i = 1; i <= n; i++) insert(i, i, a[i]);
// m个操作
while (m--)
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
insert(l, r, c);
}
// 求一下原来的数组的值,求一遍前缀和就行了
for (int i = 1; i <= n; i++) b[i] += b[i - 1];
// 将数组输出
for (int i = 1; i <= n; i++) printf("%d ", b[i]);
return 0;
}
二维差分
概念
- 构造一个b矩阵
- b数组是假设出来的
- b数组的性质:使得a矩阵是b矩阵的前缀和
- 差分都不需要考虑构造,一开始让a,b数组都为0,然后将a中的每个元素一个个插进去就行了
- 插入a数组的每个元素的例子:
- 插入a数组的每个元素的例子:
- 差分只需要考虑如何去更新即可
- 一维差分给其中的一个元素加上一个值
- 类比:二维差分给其中一个矩阵加上一个值即可
题目
代码
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q; // 矩阵的长、宽、操作个数
int a[N][N], b[N][N]; // a是原矩阵, b是差分矩阵
// 插入函数
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]);
// 假定a数组是空的,然后再插入元素
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
insert(i, j, i, j, a[i][j]);
// 进行q次操作
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;
}
核心:
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;
}