1.差分的基本概念:
如果有一数列 a[1],a[2],.…a[n]
且令 b[i]=a[i]-a[i-1],b[1]=a[1]
那么就有
a[i]=b[1]+b[2]+.…+b[i]
=a[1]+a[2]-a[1]+a[3]-a[2]+.…+a[i]-a[i-1]
此时b数组称作a数组的差分数组
换句话来说a数组就是b数组的前缀和数组 例:
原始数组a:9 3 6 2 6 8
差分数组b:9 -6 3 -4 4 2
可以看到a数组是b的前缀和
那么现在有一个任务:
在区间[left,right]上加一个常数c。
我们可以利用原数组就是差分数组的前缀和这个特性,来解决这个问题。显然可得出公式:b[left]+=c,b[right+1]−=c
同样如果通过以上问题让求某一区间的和,那么前缀和也同样能够完成,但是如果操作的次数过大
那么前缀和显然会超时,但是同样有解决的方式例如 树状数组,线段树。
相对于代码长度而言,使用差分的思想求解会变得异常简单。
下面看例题:
1.转自:https://blog.youkuaiyun.com/zsyz_ZZY/article/details/79918809
有n个数,m个操作,每一次操作,将x~y区间的所有数增加z;
最后有q个询问,每一次询问求出x~y的区间和。
分析:首先我们得到一个原数组a,然后
设d[i]=a[i]-a[i-1] (1<i≤n,d[1]=a[1]);//差分数组
设f[i]=f[i-1]+d[i] (1<i≤n,f[1]=d[1]=a[1]);
设sum[i]=sum[i-1]+f[i] (1<i≤n,sum[1]=f[1]=d[1]=a[1])。//区间求和
f数组就是最上面的b数组
2.同样利用差分数组对某一区间的值进行修改,sum数组保存的就是前n项的和
只对区间两端的值进行修改,是因为每次的 f[i] 数组都包含着 f[i-1]+d[i],即如果在修改区间[left,right]内的话,从区间left开始以后的每一项都加上了修改值z,然后到最后一项right+1时就把z减掉
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<vector>