前面一篇中介绍了前缀和的概念,这里继续介绍差分,实际上差分就是前缀的逆运算。
一维数组差分
前面我们已经知道了前缀和数组中的每个变量就是原数组中相应下标变量以及它前面若干个变量的和,对一个已经存入变量的数组a[n],我们构造一个差分数组d[n],那么原数组就是差分数组的前缀和数组。
例如,假设a数组中的数分别为: 1 2 3 4 5 6
那么,它的差分数组d中的变量就是: 1 1 1 1 1 1
在上述数组中,a[3]=d[1]+d[2]+d[3]=1+1+1=3
那么,我们怎么用代码构造一个一维差分数组呢?
假设我们有一个已经存入数据的数组a[n]
for(int i=1;i<=n;i++)
d[i]=a[i]-a[i-1];
现在我们已经知道什么是差分以及怎么构造一个差分数组了,那么,它有什么实际用处呢?
细心的朋友已经发现了,我们可以利用差分数组得到原数组,因为原数组就是差分数组的前缀和数组,要求a[i]的话,就要从d[1]一直加到d[i],所以如果我们想要对原数组的某一个区间范围内的数加上或者减去一个数的话,我们只需要对差分数组进行操作,然后用差分数组复原原数组就可以得到结果。
例如,我们想要对数组a中下标l到r的变量都加上一个整数c,我们对它的差分数组进行如下操作
d[l]+=c;
d[r+1]-=c;
for(int i=1;i<=n;i++)
a[i]=a[i-1]+d[i];
这样就可以得到我们想要达到的效果,比暴力法一个个加要快上不少,特别是修改次数比较多的情况下,比较耗费时间。
二维数组差分
我们知道,差分就是前缀和的逆操作,所以原二维数组就是它的二位差分数组的前缀和数组。我们通过二维前缀和的构造方法就可以逆推出二维差分数组的构造方式。
构造二位前缀数组:
for(int i=1;i<=n;i++)
for(int j=1;j<n=;j++)
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
构造二维差分数组:
d[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
和一维差分数组一样,我们对下标(x,y)对应的差分数组变量进行操作也会影响到它之后的原数组中的变量。
假设现在我们想让x1,y1 到x2,y2之间的变量全都加上整数c
那么我们可以
d[x1][y1]+=c;
d[x2+1][y1]-=c;
d[x1][y2+1]-=c;
d[x2+1][y2+1]+=c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+d[i][j];
构造原数组的时候就想着原数组就是差分数组的前缀和数组就很容易理解了,具体原理图可以参考我的上一篇介绍前缀和的文章。
新人创作,如有错误敬请指出,欢迎各位私信和我交流,一起进步。