前缀和、差分

一维前缀和

包含 n 个元素的数组 a r r arr arr
询问 q 次 [ L , R ] [L, R] [L,R](下标从 L 到 R)的区间和 s u m [ L , R ] sum[L, R] sum[L,R]
时间复杂度为 O ( n q ) O(nq) O(nq)

例如:
给出数组 arr : 1 3 7 5 2
询问区间和:
[2, 4] = 7 + 5 + 2 = 14
[0, 3] = 1 + 3 + 7 + 5 = 16
[3, 4] = 5 + 2 = 7

下面给出前缀和计算公式:
s u m [ i ] = { s u m [ i − 1 ] + a r r [ i ] , i > 0 a r r [ 0 ] , i = 0 sum[i] = \begin{cases} sum[i-1] + arr[i], & i > 0\\ arr[0], & i = 0\\ \end{cases} sum[i]={sum[i1]+arr[i],arr[0],i>0i=0

那么,计算区间和 s u m [ L , R ] sum[L, R] sum[L,R] 即可用下面公式计算得到。
s u m [ L , R ] = { s u m [ R ] − s u m [ L − 1 ] , L > 0 s u m [ R ] , L = 0 sum[L, R] = \begin{cases} sum[R] - sum[L-1], & L > 0\\ sum[R], & L = 0\\ \end{cases} sum[L,R]={sum[R]sum[L1],sum[R],L>0L=0

数组   arr : 1 3 7 5 2
前缀和  sum : 1 4 11 16 18

s u m [ 2 , 4 ] = s u m [ 4 ] − s u m [ 1 ] = 18 − 4 = 14 sum[2, 4] = sum[4] - sum[1] = 18 - 4 = 14 sum[2,4]=sum[4]sum[1]=184=14
s u m [ 0 , 3 ] = s u m [ 3 ] = 16 = 16 sum[0, 3] = sum[3] = 16 = 16 sum[0,3]=sum[3]=16=16
s u m [ 3 , 4 ] = s u m [ 4 ] − s u m [ 2 ] = 18 − 11 = 7 sum[3, 4] = sum[4] - sum[2] = 18 - 11 = 7 sum[3,4]=sum[4]sum[2]=1811=7

一维差分

包含 n 个元素的数组 a r r arr arr
给出差分数组:
d [ i ] = { a r r [ i ] − a r r [ i − 1 ] , i > 0 a r r [ i ] , i = 0 d[i] = \begin{cases} arr[i] - arr[i-1], & i > 0\\ arr[i], & i = 0\\ \end{cases} d[i]={arr[i]arr[i1],arr[i],i>0i=0

数组 a r r arr arr1 3 7 5 2
差分 d d d1 2 4 -2 -3

计算差分的前缀和 s u m d sum_d sumd1 3 7 5 2,可以发现差分的前缀和 s u m d sum_d sumd a r r arr arr 相同。

现在若需要做 m 个操作 a r r [ L , R ] + v arr[L, R] + v arr[L,R]+v a r r arr arr下标从 L L L R R R 之间的值加个常数 v v v),那么时间复杂度为 O ( n m ) O(nm) O(nm)

现给出 3 个操作: a r r [ 2 , 4 ] + 5 arr[2, 4] + 5 arr[2,4]+5 a r r [ 1 , 3 ] + 2 arr[1, 3] + 2 arr[1,3]+2 a r r [ 0 , 2 ] − 3 arr[0, 2] - 3 arr[0,2]3,即

arr[0] - 3; 
arr[1] + 2 - 3; 
arr[2] + 5 + 2 - 3; 
arr[3] + 5 + 2; 
arr[4] + 5;

那么数组 a r r arr arr 变为 -2, 2, 11, 12, 7

利用差分,给出结论:
a r r [ L , R ] + v    ⟺    d [ L ] + v , d [ R + 1 ] − v arr[L, R] + v \iff d[L] + v, d[R+1] - v arr[L,R]+vd[L]+v,d[R+1]v
a r r [ L , R ] + v    ⟺    { d [ L ] + v , d [ R + 1 ] − v , i > 0 d [ L ] + v , R = n − 1 arr[L, R] + v \iff \begin{cases} d[L] + v, d[R+1] - v, & i > 0\\ d[L] + v, & R = n-1\\ \end{cases} arr[L,R]+v{d[L]+v,d[R+1]v,d[L]+v,i>0R=n1

如例子中:
a r r [ 2 , 4 ] + 5    ⟺    d [ 2 ] + 5 arr[2, 4] + 5 \iff d[2] + 5 arr[2,4]+5d[2]+5
a r r [ 1 , 3 ] + 2    ⟺    d [ 1 ] + 2 , d [ 4 ] − 2 arr[1, 3] + 2 \iff d[1] + 2, d[4] - 2 arr[1,3]+2d[1]+2,d[4]2
a r r [ 0 , 2 ] − 3    ⟺    d [ 0 ] − 3 , d [ 3 ] + 3 arr[0, 2] - 3 \iff d[0] - 3, d[3] + 3 arr[0,2]3d[0]3,d[3]+3
得到 d d d-2 4 9 1 -5
计算新的差分 d d d 的前缀和 s u m d sum_d sumd-2 2 11 12 7,正好是经过 a r r [ 2 , 4 ] + 5 arr[2, 4] + 5 arr[2,4]+5 a r r [ 1 , 3 ] + 2 arr[1, 3] + 2 arr[1,3]+2 a r r [ 0 , 2 ] − 3 arr[0, 2] - 3 arr[0,2]3 之后的 a r r arr arr

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

friedrichor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值