当前位置: 首页 > news >正文

前缀和(一维, 二维)

一.为什么我们要学前缀和

这里我想通过一道例题来解释为什么我们需要学前缀和?学前缀和有什么好处?

P8218 【深进1.例1】求区间和

题目描述

给定由nnn个正整数组成的序列a1,a2,⋯ ,ana_1, a_2, \cdots, a_na1,a2,,anmmm个区间[li,ri][l_i,r_i][li,ri],分别求这
mmm个区间的区间和。

输入格式

第一行包含一个正整数nnn,表示序列的长度。

第二行包含nnn个正整数a1,a2,⋯ ,ana_1,a_2, \cdots ,a_na1,a2,,an

第三行包含一个正整数mmm,表示区间的数量。

接下来mmm行,每行包含两个正整数li,ril_i,r_ili,ri,满足1≤li≤ri≤n1\le l_i\le r_i\le n1lirin

输出格式

mmm行,其中第iii行包含一个正整数,表示第iii组答案的询问。

输入输出样例 #1

输入 #1

4 4 3 2 1 2 1 4 2 3

输出 #1

10 5

说明/提示

样例解释

111到第444个数加起来和为101010。第222个数到第333个数加起来和为555

数据范围

对于50%50 \%50%的数据:n,m≤1000n,m\le 1000n,m1000

对于100%100 \%100%的数据:1≤n,m≤1051 \le n, m\le 10^51n,m1051≤ai≤1041 \le a_i\le 10^41ai104

对于这道题,如果我们根据输入临时求区间[l, r]的和,大概率会写出这样的代码

for(inti=1;i<=m;i++){cin>>l>>r;sum=0;for(intj=l;j<=r;j++){sum+=a[j];}}

显然,这样的算法的时间复杂度是O(mn)O(mn)O(mn), 肯定会超时,这时我就想引出前缀和,通过此法,可以极大压缩时间复杂度,达到以空间换时间的效果

二.前缀和原理

1.一维前缀和


如图所示,易得

prefixSum[i]=A[1]+A[2]+⋯+A[i−1]+A[i]prefixSum[i] = A[1] + A[2] + \dots + A[i - 1] + A[i]prefixSum[i]=A[1]+A[2]++A[i1]+A[i]

依据此公式我们可以非常轻松的求出[l,r][l, r][l,r]上数组AAA元素的和

即,suml,r=prefixSum[r]−prefixSum[l−1]sum_{l, r} = prefixSum[r] - prefixSum[l - 1]suml,r=prefixSum[r]prefixSum[l1]

和我们高中所学的数列是一个原理

在我们掌握了这个知识点之后, 只需要提前准备好prefixSumprefixSumprefixSum数组,上面那道题就可以这样求解了

for(inti=1;i<=m;i++){cin>>l>>r;sum=prefixSum[r]-prefixSum[l-1];}

此外前缀和还有一个递推公式可以帮助我们求prefixSumprefixSumprefixSum数组

prefixSum[i]=prefixSum[i−1]+A[i]prefixSum[i] = prefixSum[i - 1] + A[i]prefixSum[i]=prefixSum[i1]+A[i]

代码示例

for(inti=1;i<=n;i++){cin>>A[i];prefixSum[i]=prefixSum[i-1]+A[i];}

2.二维前缀和

在介绍完了以上比较简单的一维前缀和之后, 我还想再解释一下二维前缀和, 如果遇到给定矩形区域的范围, 我们是否也能用O(1)O(1)O(1)的时间复杂度求出区域内的数值之和呢? 答案当然是肯定的


同样的道理
prefixSum[i][j]=A[1][1]+A[1][2]+⋯+A[1][j−1]+A[1][j]+A[2][1]+A[2][2]+⋯+A[2][j−1]+A[2][j]+…+A[i][1]+A[i][2]+⋯+A[i][j−1]+A[i][j] \begin{aligned} prefixSum[i][j] = &A[1][1] + A[1][2] + \dots + A[1][j - 1] + A[1][j] +\\ &A[2][1] + A[2][2] + \dots + A[2][j - 1] + A[2][j] +\\ & \dots\\ &+ A[i][1] + A[i][2] + \dots + A[i][j - 1] + A[i][j] \end{aligned}prefixSum[i][j]=A[1][1]+A[1][2]++A[1][j1]+A[1][j]+A[2][1]+A[2][2]++A[2][j1]+A[2][j]++A[i][1]+A[i][2]++A[i][j1]+A[i][j]
由此我们可以得出
(x1,y1)(x1, y1)(x1,y1)为左上角,(x2,y2)(x2, y2)(x2,y2)为右下角的矩形区域内的元素和公式

sum(x1,y1),(x2,y2)=prefixSum[x2][y2]−prefixSum[x2][y1−1]−prefixSum[x1−1][y2]+prefixSum[x1−1][y1−1] \begin{aligned} sum_{(x1, y1), (x2, y2)} =& prefixSum[x2][y2] - prefixSum[x2][y1 - 1] -\\ &prefixSum[x1 - 1][y2] + prefixSum[x1 - 1][y1 - 1] \end{aligned}sum(x1,y1),(x2,y2)=prefixSum[x2][y2]prefixSum[x2][y11]prefixSum[x11][y2]+prefixSum[x11][y11]

例如, 我们可以轻松算出

sum(2,2),(3,4)=7+7+3+1+10+1=29sum_{(2, 2), (3, 4)} = 7 + 7 + 3 + 1 + 10 + 1 = 29sum(2,2),(3,4)=7+7+3+1+10+1=29


同样也有
sum(2,2),(3,4)=prefixSum[3][4]−prefixSum[3][1]−prefixSum[1][4]+prefixSum[1][1]=52−9−16+2=29 \begin{aligned} sum_{(2, 2), (3, 4)} =& prefixSum[3][4] - prefixSum[3][1] -\\ &prefixSum[1][4] + prefixSum[1][1] \\ =&52 - 9 - 16 + 2 \\ =&29 \end{aligned}sum(2,2),(3,4)===prefixSum[3][4]prefixSum[3][1]prefixSum[1][4]+prefixSum[1][1]52916+229

其实原理非常简单,利用容斥定理,我们要求出一个矩形区域内的元素和,就用
“一个大的,减去两边两个小的,然后多减的一块再加上就行”, 这点结合图示非常容易理解

这里还有一个二维前缀和的递推公式可以辅助我们求prefixSumprefixSumprefixSum数组

prefixSum[i][j]=prefixSum[i][j−1]+prefixSum[i−1][j]−prefixSum[i−1][j−1]+A[i][j]prefixSum[i][j] = prefixSum[i][j - 1] + prefixSum[i - 1][j] - prefixSum[i - 1][j - 1] + A[i][j]prefixSum[i][j]=prefixSum[i][j1]+prefixSum[i1][j]prefixSum[i1][j1]+A[i][j]

代码如下

for(inti=1;i<=n;i++){for(intj=1;j<=m;j++){cin>>A[i][j];prefixSum[i][j]=prefixSum[i-1][j]+prefixSum[i][j-1]-prefixSum[i-1][j-1]+A[i][j];}}

三.总结

不论是一维前缀和还是二维前缀和,都是一种对数据的预处理,然后利用空间换时间的策略,如果这块掌握好了,可以极大的减少时间复杂度,提升代码的通过率

后续如果有空,我会在下面贴一些关于本节,且比较适合新手练手的题目…

http://www.jsqmd.com/news/195737/

相关文章:

  • 异步通知在字符设备驱动中的应用详解
  • 2026年度盘点!小说写作工具使用指南: 智能续写/世界观构建/卡文突破/多模创作
  • 智能家居播报:让家电用家人声音提醒事项
  • 学历低?靠系统学习,也能逆袭优质实习单位
  • start_app.sh脚本解读:自动化启动GLM-TTS服务的秘密
  • 桥式整流电路启动冲击电流:整流二极管保护策略
  • 短文本5秒生成?实测GLM-TTS在A100上的响应速度
  • [特殊字符]_高并发场景下的框架选择:从性能数据看技术决策[20260104171236]
  • 基于GLM-TTS的语音博客平台设计:文字一键转播客节目
  • dify工作流集成设想:将GLM-TTS嵌入低代码语音生成系统
  • 服务器长时间任务管理:screen命令深度剖析
  • 零基础搭建SNES ROM资源库(基于Batocera整合包)
  • Linux 内存管理:匿名内存映射简析
  • 半加器与全加器设计原理:一文说清基本逻辑结构
  • ⚡_实时系统性能优化:从毫秒到微秒的突破[20260104165159]
  • 图解说明Vivado注册2035在Artix-7环境中的修复步骤
  • [特殊字符]_微服务架构下的性能调优实战[20260104165708]
  • SpringBoot+Vue 在线拍卖系统管理平台源码【适合毕设/课设/学习】Java+MySQL
  • Java Web 足球社区管理系统系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】
  • [特殊字符]_可扩展性架构设计:从单体到微服务的性能演进[20260104170217]
  • 前后端分离图书个性化推荐系统系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程
  • [特殊字符]️_开发效率与运行性能的平衡艺术[20260104170726]
  • OSI 七层模型太难背?看这个“快递流水线”比喻,一眼就懂!(文章附速记彩蛋)
  • 从零实现Multisim14.0主数据库恢复的操作指南
  • 使用KubeSphere管理GLM-TTS在国产化芯片环境运行
  • GLM-TTS采样率怎么选?24kHz与32kHz音质实测对比分析
  • 语音合成中的笑声哭声插入:丰富情感表达维度
  • 【大数据架构-数据中台(2)】数据中台建设与架构:从战略到落地的完整方法论
  • GLM-TTS能否用于艺术展览?作品解读语音沉浸体验
  • 网站证书自动续订失败的问题解决,原来是续订指令certbot renew出错,导致crontab定时任务续订失败