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

【算法/学习】前缀和差分

前缀和&&差分目录

1. 前缀和的概念及作用

🌈概念

🌈用途

🌙一维前缀和

🌙二维前缀和

2. 差分的概念及用途

🌈概念:

🌈用途

🌙一维差分

🌙二维差分


1. 前缀和的概念及作用

🌈概念

前缀和:

🎈对于一个给定的数列a,他的前缀和数中 s 中 s[ i ] 表示从第一个元素到第 i 个元素的总和。即s[ i ] = s[ i - 1 ] + a[ i ];

比如: s[ 1 ] = s[ 0 ] + a[ 1 ]。   

注意:在使用前缀和和差分的时候,一般下标 0  不参与的运算,统一的将下表设置为从1开始,具体是要考虑到我们的边界问题,也就是S[1]的求法问题,为了保证我们循环的统一性,我们要将S[0]设置为0,所以我们索性就将下标从1开始设置起,这样也有利于我们后面的初始化。

🌈用途

可以用于一维前缀和和二维前缀和。

模板如下:

🌙一维前缀和

核心代码如下:

s[i] = s[i-1] + a[i]
s[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = s[r] - s[l - 1]

🧩例题如下:

 题目练习: AcWing 795. 前缀和

思路:

首先做一个预处理,定义一个s数组,让s[ i ]代表 a 数组前 i 个数的和。

然后运用求一维前缀和运算的公式 s[i] = s[i-1] + a[i] 

再进行查询操作:即s[ r ] - s[ l - 1] ,这样使得求 [ l, r ]的和的时间复杂度变为 O (1).

注意:求 [ l, r ]的和是s[ r ] - s[ l - 1],之所以要 l - 1是因为,a[ l ] 也包括在内

因为a[l] + ... + a[r] = s[r] - s[l - 1]

AC代码如下:

#include <iostream>
using namespace std;const int N = 1e5+10;
int a[N], s[N];int main(){int n, m, x;cin>>n>>m;for(int i = 1; i <= n; i++) cin>>a[i];for(int i = 1; i <= n; i++) s[i] = a[i] + s[i - 1];int l, r;while(m--){cin>>l>>r;cout<<s[r] - s[l - 1]<<endl;}return 0;
}


🌙二维前缀和

和一维前缀和的原理类似,只不过二维前缀和求的是一个矩阵中所有元素的和。

如下图:


因此通过上面的图我们就可以更好理解下图来推导公式了:

s[ i ][ j ] 即为框内所有数的和:s[ i ][ j ]=s[ i ][ j - 1 ]+s[ i - 1 ][ j ] - s[ i - 1 ][ j - 1 ]+a[ i ][ j ];

而(x1, y1) 到 (x2, y2)的矩阵大小为s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]

核心代码:

s[x][y]=s[x][y-1]+s[x-1][y]-s[x-1][y-1]+a[x][y];
s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]

🧩例题如下:

  题目练习: AcWing 796. 子矩阵的和

思路:

先做一个预处理,定义一个s矩阵,s[ i ][ j ]代表 a 矩阵 从(0,0)到(i,j)的矩阵和。

然后运用求一维前缀和运算的公式 s[i] = s[i-1] + a[i] 

再进行查询操作:即s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]。

这样使得求 (x1, y1) 到 (x2, y2)的矩阵大小的和的时间复杂度变为 O (1).

AC代码如下:

#include <iostream>
using namespace std;const int N = 1005;
int a[N][N], s[N][N];int main(){int n, m, q;cin >> n >> m >> q;//第一步:输入矩阵的值for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){cin >> a[i][j];}}//第二步:求矩阵前缀和for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++) {s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];}}//第三步:查找(x1,y1)到(x2,y2)的矩阵大小while (q--){int x1, x2, y1, y2;cin >> x1 >> y1 >> x2 >> y2;printf("%d\n", s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]);}return 0;
}


2. 差分的概念及用途

🌈概念:

差分:

🎈 类似于数学中的求导和积分,差分可以看成前缀和的逆运算

对于一个给定的数列a,其中a[1],a[2]…a[n]作为前缀和。它的差分数组中 b 中 b[ i ] 表示从第 i - 1个元素到第 i 个元素的差值。即b[ i ] = a[ i ] - s[ i - 1 ];

一维差分数组的构造也很简单,即a[1] = b[1], b[2] = a[2] - a[1], b[n] = a[n] - a[n-1];

注意:刚开始时可以初始化数组a,b全部为0,输入a数组后;在构造时,只需要将b[1]看做在[1, 1]区间上加上a[1]; b[2] 看作在[2, 2]区间上加上a[2];

🌈用途

🌙一维差分

      差分数组的好处是可以简化运算,例如想要给一个区间 [l,r] 上的数组加一个常数c原始的方法是依次加上c,这样的时间复杂度是O(n)的。但是如果采用差分数组的话,可以大大降低时间复杂度到O(1)。

       因此只需要将b[l] = b[l] + c 即可,这样l之后的数字会依次加上常数c,而在 b[r]处,将b[r+1] = b[r+1] - c ,这样r之后的数组又会恢复原值,仅需要处理这两个边界的差分数组即可。时间复杂度大大降低。

核心代码如下:

b[i]=a[i]-a[i-1];
a[i] = b[i] + a[i - 1];

🧩例题如下:

题目练习: AcWing 797. 差分

思路:

首先做一个预处理,定义一个b数组,让b[ i ]代表a[ i ] - a[ i -1 ].

因此只需要将b[l] = b[l] + c 即可,这样l之后的数字会依次加上常数c,而在 b[r]处,将b[r+1] = b[r+1] - c ,这样r之后的数组又会恢复原值,仅需要处理这两个边界的差分数组即可。

AC代码如下:

#include <iostream>
using namespace std;const int N = 1e5 + 5;
int b[N], a[N];int main()
{int n, m;cin>>n>>m;for (int i = 1; i <= n; i++){scanf("%d", &a[i]);b[i]=a[i]-a[i-1];}while(m--){int l,r,c;cin>>l>>r>>c;b[l]+=c;b[r+1]-=c;}for (int i = 1; i <= n; i++){a[i] = b[i] + a[i - 1];printf("%d ", a[i]);}return 0;
}


🌙二维差分

如果扩展到二维,我们需要让二维数组被选中的子矩阵中的每个元素的值加上c,是否也可以达到O(1)的时间复杂度。答案是可以的,考虑二维差分

a[][]数组是b[][]数组的前缀和数组,那么b[][]a[][]的差分数组

原数组: a[i][j]

我们去构造差分数组: b[i][j]

使得a数组中a[i][j]b数组左上角(1,1)到右下角(i,j)所包围矩形元素的和。

如何构造b数组呢?

其实关于差分数组,我们并不用考虑其构造方法,因为我们使用差分操作在对原数组进行修改的过程中,实际上就可以构造出差分数组。

同一维差分,我们构造二维差分数组目的是为了 让原二维数组a中所选中子矩阵中的每一个元素加上c的操作,可以由O(n*n)的时间复杂度优化成O(1)

已知原数组a中被选中的子矩阵为 以(x1,y1)为左上角,以(x2,y2)为右下角所围成的矩形区域;

始终要记得,a数组是b数组的前缀和数组,比如对b数组的b[i][j]的修改,会影响到a数组中从a[i][j]及往后的每一个数。

假定我们已经构造好了b数组,类比一维差分,我们执行以下操作
来使被选中的子矩阵中的每个元素的值加上c

b[x1][y1] + = c ;

b[x1,][y2+1] - = c;

b[x2+1][y1] - = c;

b[x2+1][y2+1] + = c;

每次对b数组执行以上操作,等价于:

b[x1][y1] += c ; 对应图1 ,让整个a数组中蓝色矩形面积的元素都加上了c。
b[x1,][y2 + 1] -= c ; 对应图2 ,让整个a数组中绿色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2 + 1][y1] -= c ; 对应图3 ,让整个a数组中紫色矩形面积的元素再减去c,使其内元素不发生改变。
b[x2 + 1][y2 + 1] += c; 对应图4,让整个a数组中红色矩形面积的元素再加上c,红色内的相当于被减了两次,再加上一次c,才能使其恢复。

核心代码如下:

b[i][j] = a[i][j] − a[i − 1][j] − a[i][j − 1] + a[i −1 ][j − 1]
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;

题目练习: AcWing 798. 差分矩阵

AC代码如下:

#include <iostream>
using namespace std;const int N = 1005;
int a[N][N], b[N][N];int main(){int n, m, q;cin >> n >> m >> q;for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++) {cin >> a[i][j];b[i][j] = a[i][j] - a[i - 1][j] - a[i][j - 1] + a[i - 1][j - 1];}}while (q--){int x1, x2, y1, y2, c;cin >> x1 >> y1 >> x2 >> y2 >> c;b[x1][y1] += c, b[x2 + 1][y2 + 1] += c;b[x1][y2 + 1] -= c, b[x2 + 1][y1] -= c;}for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + b[i][j];cout << a[i][j] << " ";}cout << endl;}return 0;
}

相关文章:

【算法/学习】前缀和差分

前缀和&&差分目录 1. 前缀和的概念及作用 &#x1f308;概念 &#x1f308;用途 &#x1f319;一维前缀和 &#x1f319;二维前缀和 2. 差分的概念及用途 &#x1f308;概念&#xff1a; &#x1f308;用途 &#x1f319;一维差分 &#x1f319;二维差分 1. …...

idea Project 不显示文件和目录

idea Project 不显示文件和目录 File - Close Project - 重新打开项目即可删除.idea文件夹&#xff0c;重新打开项目即可。 原因分析: 可能与使用不同ide例如java、python打开同一项目有关 参考: https://blog.csdn.net/hgnuxc_1993/article/details/132595900 解决打开IDE…...

Linux--Socket编程预备

目录 1. 理解源 IP 地址和目的 IP 地址 2.端口号 2.1端口号(port)是传输层协议的内容 2.2端口号范围划分 2.3理解 "端口号" 和 "进程 ID" 2.4理解 socket 3.传输层的典型代表 3.1认识 TCP 协议 3.2认识 UDP 协议 4. 网络字节序 5. socket 编程接…...

100个python的基本语法知识【下】

50. 压缩文件&#xff1a; import zipfilewith zipfile.ZipFile("file.zip", "r") as zip_ref:zip_ref.extractall("extracted")51. 数据库操作&#xff1a; import sqlite3conn sqlite3.connect("my_database.db") cursor conn.c…...

Git如何将一个分支上的修改转移到另一个分支

在我们使用git进行版本控制时&#xff0c;当代码写错分支&#xff0c;怎么将这些修改转移到正确的分支上去呢&#xff1f;这时&#xff0c;我们可以使用git stath命令来暂存我们的修改&#xff0c;然后再切换到其他分支 未commit&#xff08;提交&#xff09;操作时 1. 先将修…...

jvm-证明cpu指令是乱序执行的案例

package jvm;/*** 证明cpu指令是乱序执行的** author 1* version 1.0* description: TODO* date 2024-07-19 9:31*/ public class T04_Disorder {private static int x 0, y 0;private static int a 0, b 0;public static void main(String[] args) throws InterruptedExcep…...

《流程引擎原理与实践》开源电子书

流程引擎原理与实践 电子书地址&#xff1a;https://workflow-engine-book.shuwoom.com 第一部分&#xff1a;流程引擎基础 1 引言 1.1 流程引擎介绍 1.2 流程引擎技术的发展历程 1.3 相关产品国内外发展现状 1.4 本书的内容和结构安排 2 概念 2.1 基础概念 2.2 进阶…...

谷粒商城实战笔记-52~53-商品服务-API-三级分类-新增-修改

文章目录 一&#xff0c;52-商品服务-API-三级分类-新增-新增效果完成1&#xff0c;点击Append按钮&#xff0c;显示弹窗2&#xff0c;测试完整代码 二&#xff0c;53-商品服务-API-三级分类-修改-修改效果完成1&#xff0c;添加Edit按钮并绑定事件2&#xff0c;修改弹窗确定按…...

uni-app 影视类小程序开发从零到一 | 开源项目分享

引言 在数字娱乐时代&#xff0c;对于电影爱好者而言&#xff0c;随时随地享受精彩影片成为一种日常需求。分享一款基于 uni-app 开发的影视类小程序。它不仅提供了丰富的影视资源推荐&#xff0c;还融入了个性化知乎日报等内容&#xff0c;是不错的素材&#xff0c;同时对电影…...

Python使用正则替换字符串

Python小技&#xff1a;使用正则替换字符串 java中有String.replaceAll()方法使用正则替换字符串&#xff0c; 在Python中&#xff0c;字符串也有一个replace方法&#xff0c;但是这个方法只能精准替换&#xff0c; 如果想正则替换&#xff0c;就要改成re.sub方法&#xff0c;而…...

每日一练,java03

目录 题目wait()、notify()和notifyAll()方法的特性和使用场景wait() 方法notify() 方法notifyAll() 方法使用场景 注意事项 题目 选自牛客网 1.下面关于JAVA的垃圾回收机制&#xff0c;正确的是&#xff08; &#xff09; A.当调用“System.gc()”来强制回收时&#xff0c;系…...

【机器学习】深入理解损失函数(Loss Functions)

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解损失函数(Loss Functions)什么是损失函数?常见损失函数类型1. 均方误差…...

python实现特征检测算法3

python实现SIFT(尺度不变特征变换)算法、SURF(Speeded Up Robust Features)算法 1.SIFT算法详解算法步骤Python实现详细解释优缺点应用领域2.SURF算法详解算法步骤Python实现详细解释SURF算法原理优缺点应用领域尺度不变特征变换(SIFT,Scale-Invariant Feature Transform…...

软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策

引言 原文链接 近日&#xff0c;一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新&#xff0c;如同一颗隐形炸弹在全球范围内引爆&#xff0c;…...

Redis 主从搭建

Redis主从搭建 7.2.5 文章目录 一. 同主机搭建Redis主从1. 环境介绍2. 环境前准备工作3. 安装 Redis 7.2.54. redis 配置修改并且启动4.1 修改配置文件4.2 编写启动脚本 5. 开启主从5.1 开启5.2 主库实例查看主从信息5.3 从库实例查看主从信息5.4 验证主从配置是否生效 6. 解除…...

LeetCode 129, 133, 136

文章目录 129. 求根节点到叶节点数字之和题目链接标签思路代码 133. 克隆图题目链接标签思路代码 136. 只出现一次的数字题目链接标签思路代码 129. 求根节点到叶节点数字之和 题目链接 129. 求根节点到叶节点数字之和 标签 树 深度优先搜索 二叉树 思路 由于本题需要 从…...

macOS 环境Qt Creator 快捷键

在 macOS 环境下&#xff0c;Qt Creator 是一个流行的集成开发环境&#xff08;IDE&#xff09;&#xff0c;用于开发 Qt 项目。下面是一些常用的快捷键和操作技巧&#xff0c;帮助你更高效地使用 Qt Creator 进行项目开发和管理&#xff1a; 在 macOS 中&#xff0c;Cmd 键 四…...

【C# WInForm】将TextBox从输入框设置为文本框

1.需求情形&#xff1a; textbox作为最常用的控件之一&#xff0c;通常是用来输入文本信息或者显示文字&#xff0c;但是如果要在界面中显示大段文本&#xff0c;一个带有边框、可选中的文本样式似乎不合适。像这样&#xff1a; 我需要的是这段文字不仅能跨行&#xff0c;而且…...

minio 服务docker配置

用minio docker配置了一个服务&#xff0c;分享链接始终是127.0.01开始的&#xff0c; 改成docker的host的ip则提示签名不匹配&#xff0c; 好在这个文件主要是用来下载的&#xff0c;所以可以通过设置bucket的匿名访问权限来实现下载&#xff1b; 这样不需要后面的地址参数就…...

开源模型应用落地-LangChain高阶-智能体探究-自定义agent(五)

一、前言 大模型具有非常强大的功能,可以解答疑问、撰写报告和文档、总结内容、进行翻译等各种日常工作任务。然而,大模型还可以应用于更多的场景,发挥出更强大的作用。 通过智能体,我们可以实现许多有价值的事情,比如:在日常生活中,我们能借助智能体实现智能家居的自动化…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...