使得 a[i] = b[1] + b[2] + …… + b[i]; (即数组 a 是数组 b 的前缀和)
b 称为 a 的差分,a 称为 b 的前缀和。
计算构造数组
参考条件:已知数组 a , 并且 a[i] = b[1]+b[2]+……+b[i];
因此:
b[1] = a[1]
b[2] = a[2] - a[1]
b[3] = a[3] - a[2] …
b[i] = a[i] + a[i - 1] (因为 a[i] 是 数组 b 的 前 i 项和,而 a[i- 1] 是 数组 b 的 前 i - 1 项和。两者相减,便得出 b[i])
结论:
计算构造数组 b[i] 的值有如下计算公式:
当 i = 1 时,b[1] = a[1]
当 i > 1时, b[i] = a[i] + a[i - 1]
差分的作用和原理
作用:
如引入所述,使用差分可以实现用 O(1) 的时间复杂度给原数组 a 中间的某一段连续区间全部加上一个常数 K
原理:
目标:a[L] + K , a[L+1] + K ,a[L+2] + K ,… ,a[R] + K
根据 a[i] = b[1] + b[2] + …… + b[i] 可知:
若 b[i] + K,则 a[i] ~ a[a.len - 1] 中所有数都加 K (因为数组 a 是 数组 b 的前缀和),
因为我们需要 a[L] ~ a[R] 中所有数都加 K,
所以:
b[L] + k :使得 a[L] ~ a[a.len - 1] 中的所有数全部加上 k
b[R + 1] - k : 使得 a[R + 1] ~ a[a.len - 1] 中的所有数全部减去 k
结论:
若需将 a[L] ~ a[R] 中的所有数都加 1,可进行如下步骤实现:
构造数组 b[L] + K
构造数组 b[R + 1] - K (注意在计算过程中确保不超出数组范围)
还原原数组
参考条件:a[i] = b[1] + b[2] + …… + b[i];
因此:
a[1] = b[1]
a[2] = b[2] + a[1]
a[3] = b[3] + a[2] …
a[i] = b[i] + a[i-1]
结论:
还原原数组 b[i] 的值有如下计算公式:
当 i = 1 时,a[1] = b[1]
当 i > 1时, a[i] = b[i] + a[i - 1]
实践
通过以上的分析,现在就可以来解决引入时遇到的问题:
publicstaticvoidmain(String[] args){Scanner sc =newScanner(System.in);int n = sc.nextInt();int[] a =newint[n];int l = sc.nextInt(), r = sc.nextInt(), k = sc.nextInt();for(int i =0; i < n; i++){
a[i]= sc.nextInt();}// 计算构造数组 int[] b =newint[n];
b[0]= a[0];for(int i =1; i < n; i++){
b[i]= a[i]- a[i-1];}// 差分
b[l]+= k; b[r +1]-= k;// 还原原数组
a[0]= b[0];for(int i =1; i < n; i++){
a[i]= b[i]+ a[i -1];}// 输出 for(int i =0; i < n; i++){System.out.print(a[i]+" ");}}