news 2026/8/9 2:09:18

前缀和:一维与二维

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前缀和:一维与二维

本质上有动态规划的思想。

文章目录

    • 一、一维前缀和
    • 二、二维前缀和
    • 三、零边界

一、一维前缀和

牛客 DP34.【模板】前缀和

dp[i]表示数组前i个元素之和,并额外定义dp[0] = 0

dp[i] = dp[i - 1] + arr[i]

查询闭区间[l, r]时,dp[r]包含第1个到第r个元素,再减去第1个到第l - 1个元素:

sum(l, r) = dp[r] - dp[l - 1]

代码中的数组名虽然是dp,但它保存的是预处理得到的前缀和,不是动态规划中的最优子结构结果。

importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannerin=newScanner(System.in);intn=in.nextInt();intq=in.nextInt();int[]arr=newint[n+1];long[]dp=newlong[n+1];for(inti=1;i<n+1;i++){arr[i]=in.nextInt();dp[i]=dp[i-1]+arr[i];}while(in.hasNextInt()){inta=in.nextInt();intb=in.nextInt();System.out.println(dp[b]-dp[a-1]);}}}

题目中的元素绝对值可达10^9,区间和可能超过int范围,因此前缀和数组使用long[]

二、二维前缀和

牛客 DP35.【模板】二维前缀和

dp[i][j]表示左上角(1, 1)到右下角(i, j)这一整块矩形的元素和。构造时先相加上方矩形与左侧矩形,但它们重复计算了左上角重叠区域,因此需要减去一次,再加上当前元素:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j]

查询左上角(x1, y1)到右下角(x2, y2)的子矩形时,同样使用容斥:

sum = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]

前两次减法去掉目标矩形上方与左侧的区域,但左上角区域被减了两次,所以最后要补回一次。

importjava.util.Scanner;publicclassMain{publicstaticvoidmain(String[]args){Scannerin=newScanner(System.in);intn=in.nextInt();intm=in.nextInt();intq=in.nextInt();int[][]arr=newint[n+1][m+1];long[][]dp=newlong[n+1][m+1];for(inti=1;i<n+1;i++){for(intj=1;j<m+1;j++){arr[i][j]=in.nextInt();dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+arr[i][j];}}while(in.hasNextInt()){intx1=in.nextInt();inty1=in.nextInt();intx2=in.nextInt();inty2=in.nextInt();System.out.println(dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]);}}}

三、零边界

为什么要把原数组向后平移一位?如果一维前缀和直接把dp[0]作为第一个值不是更符合直觉吗?

但是这样我们在实操的时候会遇到许多不便之处,往往需要繁杂的分类讨论,因此我们补出值为0的边界,用来统一公式。

例如查询从第1个元素开始第1个元素结束的区间时,公式会访问dp[1 - 1],也就是dp[0]。二维前缀和同理:当查询区域贴着上边界或左边界时,公式会访问第0行或第0列。预留零边界后,不需要为这些情况额外分类,也不会出现负数下标,从而我们花费了少量的空间换来了简洁的代码,优雅的思路和性能的提升。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/9 2:09:17

Unity游戏开发:数据驱动与事件架构的任务系统框架设计

1. 项目概述&#xff1a;为什么需要一个好的任务系统框架&#xff1f; 在Unity游戏开发里&#xff0c;任务系统几乎是所有RPG、MMO、开放世界乃至许多剧情驱动型游戏的核心骨架。它不仅仅是让玩家“去A点杀B只怪”那么简单&#xff0c;一个设计良好的任务系统&#xff0c;承载着…

作者头像 李华
网站建设 2026/8/9 2:09:12

VisualCppRedist AIO:一站式解决Windows软件运行库依赖问题

VisualCppRedist AIO&#xff1a;一站式解决Windows软件运行库依赖问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过新安装的软件打不开&…

作者头像 李华
网站建设 2026/8/9 2:09:06

SpringBoot+Vue大学生竞赛管理平台设计与实现

1. 项目概述&#xff1a;SpringBootVue大学生竞赛管理平台这个基于SpringBootVue技术栈的大学生竞赛管理系统&#xff0c;是我在指导毕业设计和课程设计时反复打磨的一个实战项目。它完美解决了高校竞赛活动管理中的三个核心痛点&#xff1a;赛事信息分散、报名流程繁琐、成绩统…

作者头像 李华
网站建设 2026/8/9 2:09:00

虚拟电厂多时间尺度调度优化与Matlab实现

1. 项目概述在能源转型的大背景下&#xff0c;高比例可再生能源并网已成为全球电力系统发展的必然趋势。然而&#xff0c;风电、光伏等可再生能源的间歇性和波动性给电网运行带来了巨大挑战。作为一名长期从事电力系统优化研究的工程师&#xff0c;我最近复现了一篇顶级SCI期刊…

作者头像 李华
网站建设 2026/8/9 2:07:19

C++构造函数详解:从默认构造到移动语义,掌握对象初始化的核心机制

1. 项目概述&#xff1a;从“创建对象”到“对象诞生”在C的世界里&#xff0c;我们每天都在和“对象”打交道。无论是写一个简单的学生信息管理&#xff0c;还是构建一个复杂的游戏引擎&#xff0c;第一步总是离不开“创建对象”。很多新手&#xff0c;甚至一些有经验的开发者…

作者头像 李华