【蓝桥杯C/C++组】备赛基础篇之差分算法
一、个人理解
前面学习了前缀和算法,对于访问任意区间的速度是比较快的,但如果我们要修改某个区间的数呢,对于前缀和算法来说这还是有点棘手。
所以我们来学学新的算法:差分算法!
前缀和数组储存的是前n个数的和,而差分代表的是与前一个的差值。
为什么要这么储存呢???
因为这么储存之后,我们就可以对我们的原数组进行修改,假如我们在第 l 个位置加上一个值,就会影响后面所有的数值 ,这时候我们只需要在我我们要截止的地方后面一个数(也就是r+1)加上一个数值就可以了(后面的正负相抵没有了)。这样,就只用修改两处就让我们想要修改的区间全部修改好了。
我们该如何得到我们的值呢?
想必大家都学过数学的累加,既然存的是差值,我每一个都相加不就是我们要的答案吗??
为了防止越界,标记数组的索引从1开始。x0 = 0.
二、详细代码
#include<iostream> using namespace std; const int N = 100000 + 10; int a[N], n, m;//a数组表示的是与前一个数的差值。 void insert(int l, int r, int c) { a[l] += c; a[r + 1] -= c; } int main() { int x; scanf("%d%d", &n, &m); for (int i = 1;i <= n;i++) scanf("%d", &x), insert(i, i, x); while (m--) { int l, r, c; scanf("%d%d%d", &l, &r, &c); insert(l, r, c); } for (int i = 1;i <= n;i++) { a[i] += a[i - 1]; printf("%d ", a[i]); } return 0; }
三、升级版————>差分矩阵
#include<iostream> #include<cstdio> using namespace std; const int N = 1010; int a[N][N]; void insert(int x1, int y1, int x2, int y2, int c) { a[x1][y1] += c; a[x1][y2 + 1] -= c; a[x2 + 1][y1] -= c; a[x2 + 1][y2 + 1] += c; } int main() { int n, m, q, x1, y1, x2, y2, c; scanf("%d%d%d", &n, &m, &q); for (int i = 1;i <= n;i++) for (int j = 1; j <= m; j++) scanf("%d", &c), insert(i, j, i, j, c); while (q--) { scanf("%d%d%d%d%d", &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]; printf("%d ", a[i][j]); } printf("\n"); } return 0; }