前缀和和差分算法

文章目录

    • 一维前缀和
        • 一维前缀和概念
        • 一维前缀和数组的构建
    • 二维前缀和
        • 二维前缀和概念
        • 二维前缀和数组的构建
    • 一维差分
        • 一维差分概念
        • 一维差分数组的构建
    • 二维差分
        • 二维差分概念
        • 二维差分数组的构建

一维前缀和

一维前缀和概念

一维前缀和是一种常用的数据预处理方法,它能够在O(1)的时间复杂度内快速求出数组任意子区间的和。这种方法通过构建一个前缀和数组来实现,其中每个元素表示从数组开始到当前位置的所有元素的和。

一维前缀和数组的构建

接下来让我们用一道题引入主题
在这里插入图片描述

public class Main
{public static void main(String[] args){Scanner in = new Scanner(System.in);int n=in.nextInt();int q=in.nextInt();long[] arr=new long[n+1];long[] pre=new long[n+1];//一维前缀和数组for(int i=1;i<=n;i++){arr[i]=in.nextLong();pre[i]=pre[i-1]+arr[i];//一维前缀和的构建}while((q--)>0){int l=in.nextInt();int r=in.nextInt();System.out.println(pre[r]-pre[l-1]);//一维前缀和的使用:pre[r]-pre[l-1]}}
}

一维前缀和题目链接
一维前缀和的构建就是需要求和的前一个元素的前缀和加上求和元素本身。
切记别死记模板
列如这一道题寻找数组的中心下标

class Solution {public int pivotIndex(int[] nums) {int n=nums.length;int[] lsum=new int[n];int[] rsum=new int[n];lsum[0]=rsum[n-1]=0;for(int i=1;i<n;i++){lsum[i]=lsum[i-1]+nums[i-1];}for(int i=n-2;i>=0;i--){rsum[i]=rsum[i+1]+nums[i+1];}for(int i=0;i<n;i++){if(lsum[i]==rsum[i]){return i;}}return -1;}
}

lsum数组表示的是[0,i-1]区间的前缀和,rsum数组表示的是[i+1,n-1]区间的前缀和。
在这里插入图片描述

一维前缀和的使用:pre[r]-pre[l-1]图解
在这里插入图片描述

二维前缀和

二维前缀和概念

二维前缀和是一种在二维数组或矩阵中快速计算子矩阵元素和的方法。

二维前缀和数组的构建

在二维数组中,我们首先定义一个二维数组dp,其中dp[i][j]表示从原数组左上角(1,1)到(i,j)形成的子矩阵的元素和。计算dp[i][j]的状态转移方程如下

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

这个方程的含义是,当前元素的前缀和等于其上方和左方元素的前缀和之和,减去左上角重叠部分的前缀和,再加上当前元素的值。
图解:
在这里插入图片描述
二维前缀和题目模板

public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别int n=in.nextInt();int m=in.nextInt();int q=in.nextInt();int[][] arr=new int[n+1][m+1];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){arr[i][j]=in.nextInt();}}long[][] dp=new long[n+1][m+1];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){dp[i][j]=dp[i-1][j]+dp[i][j-1]+arr[i][j]-dp[i-1][j-1];}}while((q--)>0){int x1=in.nextInt();int y1=in.nextInt();int x2=in.nextInt();int y2=in.nextInt();System.out.println(dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]);}}
}

二维前缀和的使用:dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1])

在这里插入图片描述

一维差分

一维差分概念

对于一个数列 a[i],我们需要维护的数据是“相邻两个数之差”。这种策略是,令p[i]=a[i]-a[i-1]即相邻两数的差。我们称数列 p[i] 为数列 a[i]的差分数列。差分数列可以快速的在某个区间加上加上或者减去一个数。

一维差分数组的构建

差分可以看成前缀和的逆运算
首先给定一个原数组a:a[1], a[2], a[3], a[n];
然后我们构造一个数组b : b[1], b[2], b[3], b[i];
使得 a[i] = b[1] + b[2] + b[3] + , + b[i];
1.a[1]=b[1];
2.a[2]=b[1]+b[2];
3.a[3]=b[1]+b[2]+b[3];
由1,2,3得
b[1]=a[1];
b[2]=a[2]-b[1]=a[2]-a[1];
b[3]=a[3]-b[1]-b[2]=a[3]-a[2];
也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数组。换句话说,每一个a[i]都是b数组中从头开始的一段区间和。
一维差分的构建用p[i]=a[i]-a[i-1]即可。
一维差分题目模板

public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n=in.nextInt();int m=in.nextInt();int[] arr=new int[n+10];for(int i=1;i<=n;i++){arr[i]=in.nextInt();}long[] pre=new long[n+10];for(int i=1;i<=n;i++){pre[i]=arr[i]-arr[i-1];//建立差分数组}while((m--)>0){int l=in.nextInt();int r=in.nextInt();int k=in.nextInt();pre[l]+=k;//使用差分数组pre[r+1]-=k;}for(int i=1;i<=n;i++){pre[i]+=pre[i-1];//差分数组求前缀和还原为原数组System.out.print(pre[i]+" ");}}
}

使用差分数组
pre[l]+=k;
pre[r+1]-=k;
在这里插入图片描述

二维差分

二维差分概念

二维差分是一种数据处理技术,应用于二维数组或矩阵中,用来快速计算和更新子矩阵元素的和。 它是对一维差分概念的自然扩展,旨在简化对二维数据结构中特定区域元素进行加减操作的过程,同时保持较高的计算效率。

二维差分数组的构建

由于差分可以看出前缀和的逆运算,所以差分数组可以通过前缀和数组求得。

dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + arr[i][j];//前缀和数组
arr[i][j]=dp[i][j]-dp[i-1][j]-dp[i][j-1]+dp[i-1][j-1];

二维差分题目模板

public class Main {public static void main(String[] args) {Scanner in = new Scanner(System.in);int n=in.nextInt();int m=in.nextInt();int q=in.nextInt();long[][] arr1=new long[n+2][m+2];long[][] arr2=new long[n+2][m+2];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){arr1[i][j]=in.nextLong();//构建二维差分数组arr2[i][j]=arr1[i][j]-arr1[i-1][j]-arr1[i][j-1]+arr1[i-1][j-1];}}while((q--)>0){int x1=in.nextInt();int y1=in.nextInt();int x2=in.nextInt();int y2=in.nextInt();int k=in.nextInt();//二维差分的使用arr2[x1][y1]+=k;arr2[x2+1][y1]-=k;arr2[x1][y2+1]-=k;arr2[x2+1][y2+1]+=k;}long[][] arr3=new long[n+2][m+2];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){//二维差分数组求前缀和得原数组arr3[i][j]=arr3[i-1][j]+arr3[i][j-1]-arr3[i-1][j-1]+arr2[i][j];System.out.print(arr3[i][j]+" ");}System.out.println();}}
}
    //二维差分的使用图解arr2[x1][y1]+=k;arr2[x2+1][y1]-=k;arr2[x1][y2+1]-=k;arr2[x2+1][y2+1]+=k;

在这里插入图片描述
在这里插入图片描述
原数组通过前缀和数组求差分得来。

public class Main12
{public int[] arr1={0,1,2,3,4,5,6,7,8,9,10};int n=arr1.length;int[] sum=new int[n+1];//一维前缀和数组int[] ppre=new int[n+1];//一维前缀和数组求差分的数组@Overridepublic String toString() {return "Main12{" +"sum=" + Arrays.toString(sum) +", ppre=" + Arrays.toString(ppre) +'}';}public void sum1(int[] arr2)//一维前缀和{for(int i=1;i<n;i++){sum[i]=sum[i-1]+arr2[i];}}public void ppre(int[] arr1){for(int i=1;i<n;i++){ppre[i]=sum[i]-sum[i-1];}}public static void main(String[] args) {Main12 main12=new Main12();main12.sum1(main12.arr1);main12.ppre(main12.sum);System.out.println(main12.toString());}
}

另外通过差分求原数组大家可以自己试试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/882665.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JS事件和DOM

1. DOM 1.1 基本概念 DOM&#xff0c;全称 Document Object Model&#xff0c;即文档对象模型。它是 Web 上最常用的 API 之一&#xff0c;是加载在浏览器中的文档模型&#xff0c;可以将文档表示为节点树&#xff08;或称 DOM 树&#xff09;&#xff0c;其中每个节点代表文…

【协议】IIC总线协议学习

一、IIC基本介绍 设计I2C的初衷是减少电视机等复杂电子系统内部的布线数量&#xff0c;同时也降低制造成本。通过使用只有两根线的通信总线&#xff0c;它有效地减少了器件间连接的复杂性。 IIC总线是两线制总线&#xff0c;仅有串行数据线SDA和串行时钟线SCL进行通信。减少…

【Python实例】Python读取并绘制tif数据

【Python实例】Python读取并绘制tiff数据 Python实例-以全球不透水面积数据为例数据准备&#xff1a;全球不透水面积数据基于gdal库绘制tif图基于Rasterio库绘制tif图 参考 GeoTIff 是一个标准的.tif 文件或是一个图像文件格式&#xff0c;它包含了一些额外的空间信息&#xff…

prompt learning

prompt learning 对于CLIP&#xff08;如上图所示&#xff09;而言&#xff0c;对其prompt构造的更改就是在zero shot应用到下游任务的时候对其输入的label text进行一定的更改&#xff0c;比如将“A photo of a{obj}”改为“[V1][V2]…[Vn][Class]”这样可学习的V1-Vn的token…

业务开发常见问题-并发工具类

hello&#xff0c;大家好&#xff0c;本讲我们一起聊一下常见的几个并发工具类的使用和坑&#xff01; 在日常工作中&#xff0c;我们经常会遇到多线程并发问题&#xff0c;比如ThreadLocal、锁、ConcurrentHashMap、CopyOnWriteArrayList等。那么如何正常的使用呢&#xff1f;…

【最新通知】2024年Cisco思科认证CCNA详解

CCNA现在涵盖安全性、自动化和可编程性。该计划拥有一项涵盖IT职业基础知识的认证&#xff0c;包括一门考试和一门培训课程&#xff0c;助您做好准备。 CCNA培训课程和考试最近面向最新技术和工作岗位进行了重新调整&#xff0c;为您提供了向任何方向发展事业所需的基础。CCNA认…

blender分离含有多个动作的模型,并导出含有材质的fbx模型

问题背景 笔者是模型小白&#xff0c;需要将网络上下载的fbx模型中的动作&#xff0c;分离成单独的动作模型&#xff0c;经过3天摸爬滚打&#xff0c;先后使用了blender&#xff0c;3d max&#xff0c;unity&#xff0c;最终用blender完成&#xff0c;期间参考了众多网络上大佬…

【Ansiable】ansible的模块和主机清单

目录 一、介绍一些运维自动化工具 二、Ansible 概述/简介 三、Ansible 工作机制 3.1 内部工作机制 3.2 外部工作机制 四、Ansible 执行流程 五、Ansblie 安装以及日常操作模块***** 5.1 ansible 环境安装部署 5.2 ansible 命令行模块 5.2.1 command 模块 5.2.2 shel…

明源云ERP报表服务GetErpConfig.aspx接口存在敏感信息泄露

一、漏洞简介 在访问 /service/Mysoft.Report.Web.Service.Base/GetErpConfig.aspx?erpKeyerp60 路径时&#xff0c;返回了包含敏感信息的响应。这些信息包括但不限于数据库连接字符串、用户名、密码、加密密钥等。这些敏感信息的暴露可能导致以下风险&#xff1a;数据库访问…

【IPv6】IPv6 NAT66介绍

参考链接 IPv6-to-IPv6 Network Address Translation (NAT66) (ietf.org)https://datatracker.ietf.org/doc/id/draft-mrw-nat66-00.html IPv6 NAT66 NAT66&#xff0c;全称为Network Address Translation for IPv6 to IPv6&#xff0c;是一种用于IPv6网络的地址转换技术。在…

Tkinter -- python GUI学习与使用

前言 python GUI 目前pythonGUI有很多&#xff0c;哪一个最好&#xff1f; 先说说我选择的思路&#xff0c;我的目的是开发一个易用的软件&#xff0c;最重要的是稳定&#xff0c;并且碰到问题能够解决&#xff0c;因此&#xff0c;我的目标很明确&#xff0c;有比较大的用户群…

基于Python的自然语言处理系列(39):Huggingface中的解码策略

在自然语言生成任务中&#xff0c;如何选择下一步的单词或者词语对生成的文本质量影响巨大。Huggingface 提供了多种解码策略&#xff0c;可以在不同的场景下平衡流畅度、创造力以及生成效率。在这篇文章中&#xff0c;我们将逐步介绍 Huggingface 中的几种常见解码策略&#x…

web API基础

作用和分类 作用: 就是使用 JS 去操作 html 和浏览器 分类&#xff1a; DOM (文档对象模型)、 BOM &#xff08;浏览器对象模型&#xff09; 什么是DOM DOM (Document Object Model) 译为文档对象模型&#xff0c;是 HTML 和 XML 文档的编程接口。 HTML DOM 定义了访问和操作 …

mingw64的Windows安装及配置教程gcc、g++等

mingw64.rar 链接&#xff1a;https://pan.baidu.com/s/18YrDRyi5NHtqnTwhJG6PuA 提取码&#xff1a;pbli &#xff08;免费永久有效&#xff0c;免安装&#xff0c;解压后配置环境变量即可使用&#xff09; 1 下载 解压后随便放到一个地方&#xff1a; 复制“bin”路径&am…

重磅:中国首个SVG技术标准发布,计育韬老师主笔起草

编辑搜图 中华人民共和国《融媒体 SVG 交互设计技术规范》是由复旦大学奇点新媒体研究中心等单位牵头&#xff0c;学科带头人计育韬等人主要起草&#xff0c;并于 2024 年 8 月起面向全社会行业从业者发布的最高技术标准。该标准前身为 2016 年计育韬与微信团队合作拟定的《SV…

置分辨率设置多显示器的时候提示, 某些设置由系统管理员进行管理

遇到的问题 设置分辨率设置多显示器的时候提示&#xff08;如下图所示&#xff09;&#xff1a; 某些设置由系统管理员进行管理 解决方法 先试试这个方法&#xff1a; https://answers.microsoft.com/zh-hans/windows/forum/all/%E6%9B%B4%E6%94%B9%E5%88%86%E8%BE%A8%E7%8…

强大的Python必备库,你知道几个?建议收藏!

在Python的世界里&#xff0c;库的丰富性让开发者的工作变得轻松而高效。那么&#xff0c;你知道哪些强大的Python必备库吗&#xff1f; 面对众多的Python库&#xff0c;如何选择适合自己的工具来提升开发效率和代码质量&#xff1f;&#xff0c;丰富多样的库如同一个个强大的…

AnaTraf | 提升网络性能:深入解析网络关键指标监控、TCP重传与TCP握手时间

AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 在当今的数字化时代&#xff0c;网络的稳定性和性能对企业的运营效率至关重要。无论是内部通信、应用程序的运行&#xff0c;还是对外提供服务&#xff0c;网络都发挥着关键作用。对于网络工程师或IT运维人员…

EasyX图形库的安装

前言 EasyX是一个图形库&#xff0c;可以用来做一些c/c小游戏&#xff0c;帮助学习。 一、进入EasyX官网 https://easyx.cn/ 二、点击下载EasyX 三、下载好后以管理员身份运行它 四、点击下一步 五、然后它会自动检测你的编辑器&#xff0c;用哪个就在哪个点安装 六、安装成功…

【linux问题】Linux命令行终端窗口的输出,显示不全问题

Linux命令行终端窗口的输出&#xff0c;显示不全问题 问题&#xff1a; 图中显示的是一个Linux命令行终端窗口&#xff0c; nmcli dev wifi 是一个命令——列出所有能用的Wi-Fi。 执行命令后&#xff0c;窗口输出了显示了所有能用的Wi-Fi网络列表。 但是在每一行末尾有一个“…