先来看一道例题,给定一个长度为n(n≤107)的数列{a1,a2,…,an},初始状态为0,m(m≤107)次操作,每次可以选择一个区间[l,r],使下标在这个区间内的数都加k或者都减k,求这m次操作每一个数的最后结果。(原创?)
O(n×m)暴力应该很好想,对叭~
但是呢?数据范围就是这样的不友好,怎么办?
这时候就要引入一个新的概念:差分数组
首先我们先来定义一下这个数组:
对于给定的数列A,它的差分数组B定义为:B[1]=A[1],B[i]=A[i]-A[i-1](2≤i≤n)
容易发现“前缀和数组”和“差分数组”存在着互逆运算关系,在此就不再赘述,感兴趣的大佬可以自行研究。
那么,把序列A的区间[l,r]加k(即把Al,Al+1,…,Ar都加上k),其差分数组B的变化为Bl加k,Br+1减k,其他位置不变。
可以感性的理解为,第l位比第l-1大了k,而因为加上了这个k所以第r+1位会比第r位小k,所以需要减去。
统计答案时,我们只需要把这个差分数组相加即可,因为差分数组的前缀和数组即为原序列(一定注意B[1]=A[1])。
每次操作时间复杂度O(1)。
总时间复杂度O(n+m)。
rp++