Smile, breathe and go slowly.
引入问题:
已知一个数组 a[ 10 ] ,初始值全部为1。 如果要将范围 [ 1, 5 ]之间的每一个数字都加1,应当如何操作。
最简单直接的操作就是for循环了:
for(int i=1;i<=5;i++) a[i]++;
但是如果数据范围较大,以及操作次数比较多,用for循环时间复杂度较高。
先看看什么是差分数组:
简单来说,前一个元素减去后一个元素形成的数组就是差分数组。
d[ 0 ] = a[ 0 ] ( i = 0 )
d[ i ] = a[ i ] - a[ i - 1 ] ( i > 0)
举个例子:
数组 a:
1,2,3,4,5
差分数组 d 应当是:
1,1,1,1,1 //第一个元素没有可以减的元素,所以就等于它本身
//即规定d[ 0 ] = a[ 0 ]
我们注意到:
d[ 1 ] = a[ 1 ] - a[ 0 ]
d[ 2 ] = a[ 2 ] - a[ 1 ]
d[ 3 ] = a[ 3 ] - a[ 2 ]
d[ 4 ] = a[ 4 ] - a[ 3 ]
即:
a[ 0 ] = d[ 0 ]
a[ 1 ] = d[ 1 ] + d[ 0 ]
a[ 2 ] = d[ 2 ] + d[ 1 ] + a[ 0 ]
…
可推导出 a[ i ] = d[ i ] + d[ i - 1 ] + d[ i - 2 ] + …+d[ 0 ]
所以差分数组到底有什么用呢?
回到引入问题:
要使[ 1, 5 ] 之间的每个元素都+1,用差分数组只需要这样写:
d[ 1 ]++;
d[ 5+1 ]--;
因为d[ 1 ] = a[ 1 ] - a[ 0 ],a[ 1 ]增大了,a[ 0 ]不变,所以d[ 1 ]应当加上相应的变化量。
同理,中间的元素是同步增大的,所以无需处理。
对于d [ 6 ] = a[ 6 ] - a[ 5 ],a[ 5 ]增大了&#