前缀和-蓝桥杯

一、前缀和的概念

  • 数组a[0]~ a[n-1],前缀和sum[i]等于a[0] ~ a[i]的和:

sum[0] = a[0]

sum[1] = a[0] + a[1]

sum[2] = a[0] + a[1] +a[2] ......

  • 在O(n)时间内求所有前缀和:

sum[i] = sum[i-l] +a[i]

  • a[0]一般不用。

二、前缀和与区间问题

  • 预计算出前缀和,能快速计算出区间和:

a[i] + a[i+1] + ... + a[j-1] + a[j] = sum[j]- sum[i-1]

  • 复杂度为O(n)的区间和计算,优化到了O(1)的前缀和计算。

  • 二分法是一种求解的方法。

三、前缀和与差分

  • 维差分数组 D[k] = a[k] - a[k-1],即原数组a[]的相邻元素的差

  • a[k]= D[1]+ D[2]+ ... + D[k]

  • a[ ]是D[ ]的前缀和。

  • 差分是前缀和的逆运算: 把求a[k]转化为求D的前缀和。

四、差分数组: 提升修改的效率

  • 把区间[L,R]内每个元素a[ ]加上d,只需把对应的D[ ]做以下操作:

  • 把D[L]加上d------>D[L] += d

  • 把D[R+1]减去d------>D[R+1] -= d

  • 利用D[ ],能极快解决修改区间[L,R]内元素的目的 。原来需要O(n)次计算,现在只需要O(1)。

  • 说明:前缀和a[x]= D[1] + D[2] + ... + D[x],有:

  • 1≤x≤L,前缀和a[x]不变;

  • L≤x≤R,前缀和a[x]增加了d;

  • R≤x≤N,前缀和a[x]不变,因为被D[R+1]中减去的d抵消了

五、真题实例(196号)


  • 题意

给定一个数组a[ ],一次操作是对连续的3个数做加减,经过多次操作后得到的数组,其中有一个数的绝对值最大;问这个最大的绝对值能达到多小。

  • 思考

  • 所有加减操作都是在数组内部进行,对于整个数组的和不会有影响。

  • 一次操作是对连续的3个数a[i-1]、a[i]、a[i+1],根据:

a[1] = a[1]+a[2]

a[3] = a[3]+a[2]

a[2] = a[2]-2a[2]

  • 三个数的和不变,由此联想前缀和。

  • 一次操作后的前缀和:

a[i-1]更新为a[i] + a[i-1],s[i-1]的新值等于原来的s[i]。

a[i]更新为-a[i],s[i]的新值等于原来的s[i-1]。

a[i+1]更新为a[i] + a[i+1],s[i+1]的值保持不变。

  • 结论:经过一次操作后,s[i]和s[i-1]互相交换,s[i+1]不变,s[i-1]、s[i]、s[i+1]这3个数值还在,没有出现新的数值。

  • 题目中对a[ ]的多次操作后的一个结果,对应了前缀和s[ ]的一种排列。

  • 因为a[i] = s[i]- s[i-1],对a[ ]多次操作后,新的a[ ]是:

a[1]= s[1]- s[0],a[2]= s[2] - s[1],......,a[n] = s[n] - s[n-1]

  • 经过以上转换,题目的原意:“对连续3个数做加减操作后,求最大的al能达到多小”,变成了简单问题:“数组s[ ],求max{|s[1]-s[0],|s[2]-s[1]|,.., |s[n] -s[n-1]|},且尽量小”,s[0]和s[n]保持不动,其他s[ ]可以随意变换位置。

  • 代码

  • 解析

  • 代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ranzi.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值