算法——前缀和及差分

前缀和及差分

​ 前缀和与差分是互为逆运算的两种计算方式,前缀和指的是一个数组是另一个数组中前n项元素之和,而差分指的是一个数组的前n项的和是另一个数组

​ 实际上就是,如果数组a是数组b的前缀和,那b就是a的差分

前缀和

​ 根据如上的的解释,我们可以理解为,假设有数组a[1, 2, 3, 4, 5]那么代表它的前缀和数组的数组b就是1, 3, 6, 10, 15,也就是说,a[n] = b[1] + b[2] + ... + b[n - 1] + b[n],这里我们假设数组是从下标1开始的,这样我们可以减去一步繁琐的判断

​ 通过前缀和,我们可以快速的求出原数组从lr的区间中元素的和,等于S[l ~ r] = b[r] - b[l - 1],有如下代码:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>

using namespace std;

const int N = 1e5 + 1;

int n, m;
int a[N], s[N];

int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) s[i]= s[i - 1] + a[i];
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", s[r] - s[l - 1]);
}
}

差分

​ 作为前缀和的逆运算,差分可以理解为有算数组a,它的差分数组b有如下关系

1
2
3
4
5
6
a[1] = b[1]
a[2] = b[1] + b[2]
a[3] = b[1] + b[2] + b[3]
...
a[n - 1] = b[1] + b[2] + b[3] + ... + b[n - 2] + b[n - 1]
a[n] = b[1] + b[2] + b[3] + ... + b[n - 2] + b[n - 1] + b[n]

​ 由此可见,如果ba的差分数组,那a就是b的前缀和数组,通过差分,我们可以快速的实现对一个区间内的所有元素的同增同减操作

​ 假设我们要让a[2]a[6]的元素全部+1,我们只需要让b[2] += 1b[7] -= 1即可,代码如下

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

const int N = 100010;

int a[N], b[N];

int n, m;

int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) b[i] = a[i] - a[i - 1];
while (m--) {
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
b[l] += c;
b[r + 1] -= c;
}
for (int i = 1; i <= n; ++i) {
a[i] = a[i - 1] + b[i];
printf("%d ", a[i]);
}
}
-------------本文结束感谢您的阅读-------------