浅谈前缀和

引入

如果你想维护一个数据结构,有一个序列 a,每次查询 lr 区间和(求 i=lrai),只有查询,线段树&树状数组难免有些大材小用,但是维护它效率要高,甚至要达到 O(1)

这个东西该怎么维护呢?

我们可以创造一个序列 si=j=1iai

这个序列显然可以用一种递归方式定义:

si={aii=1si1+aii>1

这样的话每次查询只需要输出 srsl1 就行了。

s 在输入时即可统计,不会增加太多常数。

这种创造 s 数组的方法叫做前缀和s 叫做对于 a 的前缀和。

应用

当然前缀和在区间求和应用领域极其有用,对于前缀和的求和性质,我们可以优化一些题目,比如 P1147

[例题1] P1569 【Generic Cow Protests】

题意简述:

将数列 a 分成几组,每组数字和 0 ,求最大组数。

我们维护一个数组 dpi 表示区间 1i 之间的最优解,我们找到两个数 i,j,统计 ai+ai+1+ai+2++aj1+aj=k=ijai,然后更新最优解即可,注意判断不可行情况 dpj<0 即可。

这个算法的时间复杂度是 O(n3) 的,显然会 TLE,我们该怎么优化呢?

我们发现,只有求和是可以优化的,我们就可以考虑维护一个前缀和数组,O(1) 解决求和问题,算法时间复杂度直接降到 O(n2)

通过这道例题我们发现前缀和真是个有用的工具,它主要用来优化区间求和问题

[例题2] P1865 A % B Problem

题意简述:

求区间质数个数。

因为是质数我们可以尝试埃氏筛,因为是求区间质数个数,所以要 for 遍历一遍,m106,时间复杂度是 O(mloglogm+n2)O(n2)

O(mloglogm) 已经很接近线性了,主要是优化 O(n2) 部分。

我们可以维护一个序列 p 表示 1p 质数个数,这个埃氏筛时即可解决。

然后求区间质数个数只需要按照前缀和方法相减即可,O(n2)O(1)!,时间复杂度立刻降到 O(mloglogm)O(m)

[例题3] P1043 数字游戏

题意简述:

给定一圈整数(一共 n个),你要按顺序将其分为 m 个部分,各部分内的数字相加,相加所得的 m 个结果 mod10 后再相乘,使最终结果最大/最小。

首先对于环状的东西首先当然要破环为链。

我们设 dpi,j,h 为从 ij 分成 h 段的最大/最小值。

我们枚举中间点 k,则转移方程如下:

dpi,j,h=max(ormin)(dpi,j,h,dpi,k,h1p=jk1ai)

  • 循环处注意先枚举区间长度,要不然会有遗漏。
  • 再枚举左右端点,区间 dp 套路。
  • 然后枚举段数用来更新。
  • 最后枚举中间点 k

大约时间复杂度是 O(n3m),跑不满的。

[例题4]P2969 [USACO09DEC]Music Notes S

题意简述:

给定序列 a,有序列 bb0ba11=1ba1ba1+a21=2ba1+a2ba1+a2+a31=3,询问 qbi

这个维护一个前缀和标记极值,然后 upper_bound 即可解决,很简单。

时间复杂度大概是 O(qlogn)

总结

前缀和主要应用于优化区间求和,对于形如i=lrai 的柿子可以优化到 O(1),做题时主要应用于 dp 的求和(虽然一般是单调队列优化)和某些区间统计问题。

posted @   yspm  阅读(667)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
😅​
点击右上角即可分享
微信分享提示