差分数组
关系:b[N]
是a[N]
的差分数组,a[N]
是b[N]
的前缀和数组。
$$
a_n = \sum_{i=1}^{n} b_i
$$
$$
b_1 = a_1
$$
$$
b_2 = a_2 - a_1
$$
$$
b_3 = a_3 - a_2
$$
$$\dots$$
$$
b_n = a_n - a_{ n-1}
$$
定义$f$为前缀和运算,则$a = f(b)$,$b = f^{-1}(a)$。求差分为求前缀和的逆运算。
求差分数组的作用在于便捷地得到一段区间[l,r]
内的数全部加上c
的结果,由于b[N]
是a[N]
的差分数组,在由b[N]
反求a[N]
时,只需要进过简单的前缀运算就可以,若b[l] +=c
,则求解的a[N]
数组在[l,n]
区间内全部都会加上c
,
差分数组的难点在于维护,而不在于构造。核心算法在于insert
函数,首先假设a[N]
全是0,则b[N]
也必然全是0,将a[i]
通过insert(i,i,a[i])
调用插入到b[N]
中,就可以构造差分数组。
void insert(int l, int r, int c){
b[l] += c;
b[r+1] -= c;
}
完整代码
#include <iostream>
using namespace std;
const int N = 100010;
int a[N], b[N];
int l, r, n, m, 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]);
for(int i = 1; i <= n; i ++) insert(i, i, a[i]);
while(m --) {
scanf("%d%d%d", &l ,&r, &c);
insert(l, r, c);
}
for (int i = 1; i <= n; i ++) b[i] += b[i-1]; // 求b的前缀数组
for (int i= 1; i <= n; i ++) printf("%d ", b[i]);
return 0;
}
循环优化
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
insert(i, i, a[i]);
}
while(m --) {
scanf("%d%d%d", &l, &r, &c);
insert(l, r, c);
}
for (int i = 1; i <= n; i ++) {
b[i] += b[i-1];
printf("%d ", b[i]);
}
return 0;
}