差分与前缀和,数组的常见预处理技巧
约定:给定数组 a[i] ,i 范围 [1 ~ n],a[0] = 0;
差分
定义:
差分数组delta[i]
delta[i] = a[i] = a[i-1];
性质:
差分数组的前n项和是原数组
a[i] = delta[1] + delta[2] + ... + delta[i];
对原数组a
整个区间的统一改动,(比如某个区间内同时加上或减去某个数字),可以通过修改差分数组delta
来实现,因为由性质1,差分数组delta
可以推出原数组a
a
的区间[l, r]
之间所有数字同时加上x
,原操作等价于以下两个操作:
delta[l] += x
delta[r+1] -= x
性质2证明:
- 因为一个区间内所有数都加,他们的差不会变(
众生平等),delta[l+1] ~ delta[r]
都不会改变 - 因为
a[l]
增加x,delta[l] = a[l] - a[l-1]
相应增加x - 因为
a[r]
增加x,delta[r+1] = a[r+1] - a[r]
相应减少x
这个操作可以用常数的时间,去对a[]数组的一个区间进行修改,在修改工作量巨大的情况下,是个不错的优化
示例:
- 输入一个数组
- 输入操作组数t,每次操作,读取l, r, x,对 [l, r] 区间的数字同时加上 x
- 输出最后操作后的结果
#include <iostream>
using namespace std;
#define MAXLEN 109
int a[MAXLEN