写这个博客主要的原因是解释另一道题运输计划的树上差分,另外也是记录一下,不然每次都以为差分好难,其实是非常容易的。
差分的定义:
我们先看看如下的数列 a a a:
1 5 6 7 4 3 2
那么假设我们需要区间修改这个数列多次,但最后只求一个数a[3]。
如果我们每次都改区间的和,那么我们必然会浪费大量时间,如果数据变大就会很慢。
想用前缀和?多次维护,只求一次,这样也没什么用呀!
那么我们只能用差分了!
就比如上面的这串数字,我们用一个数组 c f cf cf存, c f [ i ] cf[i] cf[i]代表 a [ i ] a[i] a[i]比 a [ i − 1 ] a[i-1] a[i−1]位的数大 c f [ i ] cf[i] cf[i](如果 a [ i ] < a [ i − 1 ] a[i]<a[i-1] a[i]<a[i−1], c f [ i ] cf[i] cf[i]将会是负数),即两数之差。那么很明显,初始的 c f [ i ] cf[i] cf[i]只要在读入时将 a [ i ] − a [ i − 1 ] a[i]-a[i-1] a[i]−a[i−1]存入即可。( c f [ 1 ] cf[1] cf[1]就是 a [ 1 ] a[1] a[1],因为 a [ 1 ] − a [ 0 ] ( a [ 0 ] = 0 ) = a [ 1 ] a[1]-a[0](a[0]=0)=a[1] a[1]−a[0](a[0]=0)=a[1])
如何求a[i]?
求 a [ i ] a[i] a[i]只要求出 c f [ 1 ] + c f [ 2 ] + c f [ 3 ] + . . . + c f [ i ] cf[1]+cf[2]+cf[3]+...+cf[i] cf[1]+cf[2]+cf[3]+...+cf[i]就可以了。
如何修改区间?
那如果我要把 x . . . y x...y x...y这个区间加 z z z怎么办?我们只要在 c f [ x ] cf[x] cf[x]处 + z +z +z(代表 a [ x ] . . . a [ n ] a[x]...a[n] a[x]...a[n]都+1),再在 c f [ y + 1 ] cf[y+1] cf[y+1]处-1(代表 a [ y + 1 ] . . . a [ n ] a[y+1]...a[n] a[y+1]...a[n]都 − z -z −z)。
这样就做到
a
[
x
]
.
.
.
a
[
y
]
+
z
a[x]...a[y]+z
a[x]...a[y]+z了:
欢迎看到下一期差分(1)——差分数组(待更)。