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

通俗易懂的C++前缀和与差分算法图文示例详解

1、前缀和前缀和是指某序列的前n项和可以把它理解为数学上的数列的前n项和而差分可以看成前缀和的逆运算。合理的使用前缀和与差分可以将某些复杂的问题简单化。2、前缀和算法有什么好处先来了解这样一个问题输入一个长度为n的整数序列。接下来再输入m个询问每个询问输入一对l, r。对于每个询问输出原序列中从第l个数到第r个数的和。我们很容易想出暴力解法遍历区间求和。代码如下1234567891011121314intn,m;scanf(%d%d,n,m);for(inti1;in;i)scanf(%d,a[i]);while(m--){intl,r;intsum0;scanf(%d%d,l,r);for(intil;ir;i){suma[i];}printf(%d\n,sum);}这样的时间复杂度为O(n*m)如果n和m的数据量稍微大一点就有可能超时而我们如果使用前缀和的方法来做的话就能够将时间复杂度降到O(nm),大大提高了运算效率。具体做法首先做一个预处理定义一个sum[]数组sum[i]代表a数组中前i个数的和。求前缀和运算123456constintN1e510;intsum[N],a[N];//sum[i]a[1]a[2]a[3].....a[i];for(inti1;in;i){sum[i]sum[i-1]a[i];}然后查询操作12scanf(%d%d,l,r);printf(%d\n, sum[r]-sum[l-1]);对于每次查询只需执行sum[r]-sum[l-1]时间复杂度为O(1)原理sum[r] a[1]a[2]a[3]a[l-1]a[l]a[l1]......a[r];sum[l-1]a[1]a[2]a[3]a[l-1];sum[r]-sum[l-1]a[l]a[l1]......a[r];图解这样对于每个询问只需要执行sum[r]-sum[l-1]。输出原序列中从第l个数到第r个数的和的时间复杂度变成了O(1)。我们把它叫做一维前缀和。总结练习一道题目输入一个长度为n的整数序列。接下来再输入m个询问每个询问输入一对l, r。对于每个询问输出原序列中从第l个数到第r个数的和。输入格式第一行包含两个整数n和m。第二行包含n个整数表示整数数列。接下来m行每行包含两个整数l和r表示一个询问的区间范围。输出格式共m行每行输出一个询问的结果。数据范围1≤l≤r≤n,1≤n,m≤100000,−1000≤数列中元素的值≤1000输入样例5 32 1 3 6 41 21 32 4输出样例3610代码123456789101112131415161718#include iostreamusingnamespacestd;constintN 100010;intn, m;inta[N], s[N];intmain(){scanf(%d%d, n, m);for(inti 1; i n; i )scanf(%d, a[i]);for(inti 1; i n; i ) s[i] s[i - 1] a[i];// 前缀和的初始化while(m -- ){intl, r;scanf(%d%d, l, r);printf(%d\n, s[r] - s[l - 1]);// 区间和的计算}return0;}3、二维前缀和如果数组变成了二维数组怎么办呢先给出问题输入一个n行m列的整数矩阵再输入q个询问每个询问包含四个整数x1, y1, x2, y2表示一个子矩阵的左上角坐标和右下角坐标。对于每个询问输出子矩阵中所有数的和。同一维前缀和一样我们先来定义一个二维数组s[][],s[i][j]表示二维数组中左上角(1,1)到右下角( i,j )所包围的矩阵元素的和。接下来推导二维前缀和的公式。先看一张图紫色面积是指(1,1)左上角到(i,j-1)右下角的矩形面积, 绿色面积是指(1,1)左上角到(i-1, j )右下角的矩形面积。每一个颜色的矩形面积都代表了它所包围元素的和。从图中我们很容易看出整个外围蓝色矩形面积s[i][j] 绿色面积s[i-1][j] 紫色面积s[i][j-1]- 重复加的红色的面积s[i-1][j-1]小方块的面积a[i][j];因此得出二维前缀和预处理公式s[i] [j] s[i-1][j] s[i][j-1 ] a[i] [j] - s[i-1][ j-1]接下来回归问题去求以(x1,y1)为左上角和以(x2,y2)为右下角的矩阵的元素的和。如图紫色面积是指( 1,1 )左上角到(x1-1,y2)右下角的矩形面积 黄色面积是指(1,1)左上角到(x2,y1-1)右下角的矩形面积不难推出绿色矩形的面积 整个外围面积s[x2, y2]- 黄色面积s[x2, y1 - 1]- 紫色面积s[x1 - 1, y2] 重复减去的红色面积s[x1 - 1, y1 - 1]因此二维前缀和的结论为以(x1, y1)为左上角(x2, y2)为右下角的子矩阵的和为s[x2, y2] - s[x1 - 1, y2] - s[x2, y1 - 1] s[x1 - 1, y1 - 1]总结练习一道完整题目输入一个n行m列的整数矩阵再输入q个询问每个询问包含四个整数x1, y1, x2, y2表示一个子矩阵的左上角坐标和右下角坐标。对于每个询问输出子矩阵中所有数的和。输入格式第一行包含三个整数nmq。接下来n行每行包含m个整数表示整数矩阵。接下来q行每行包含四个整数x1, y1, x2, y2表示一组询问。输出格式共q行每行输出一个询问的结果。数据范围1≤n,m≤1000,1≤q≤200000,1≤x1≤x2≤n,1≤y1≤y2≤m,−1000≤矩阵内元素的值≤1000输入样例3 4 31 7 2 43 6 2 82 1 2 31 1 2 22 1 3 41 3 3 4输出样例172721代码1234567891011121314151617181920212223#includeiostream#includecstdiousingnamespacestd;constintN1010;inta[N][N],s[N][N];intmain(){intn,m,q;scanf(%d%d%d,n,m,q);for(inti1;in;i)for(intj1;jm;j)scanf(%d,a[i][j]);for(inti1;in;i)for(intj1;jm;j)s[i][j]s[i-1][j]s[i][j-1]a[i][j]-s[i-1][j-1];while(q--){intx1,y1,x2,y2;scanf(%d%d%d%d,x1,y1,x2,y2);printf(%d\n,s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]s[x1-1][y1-1]);}return0;}4、差分5、一维差分类似于数学中的求导和积分差分可以看成前缀和的逆运算。差分数组首先给定一个原数组aa[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]也就是说a数组是b数组的前缀和数组反过来我们把b数组叫做a数组的差分数组。换句话说每一个a[i]都是b数组中从头开始的一段区间和。考虑如何构造差分b数组最为直接的方法如下a[0 ] 0;b[1] a[1] - a[0];b[2] a[2] - a[1];b[3] a [3] - a[2];........b[n] a[n] - a[n-1];图示:我们只要有b数组通过前缀和运算就可以在O(n)的时间内得到a数组 。知道了差分数组有什么用呢 别着急慢慢往下看。话说有这么一个问题给定区间[l ,r ]让我们把a数组中的[ l, r]区间中的每一个数都加上c,即 a[l] c , a[l1] c , a[l2] c ,,,,,, a[r] c;暴力做法是for循环l到r区间时间复杂度O(n)如果我们需要对原数组执行m次这样的操作时间复杂度就会变成O(n*m)。有没有更高效的做法吗? 考虑差分做法(差分数组派上用场了)。始终要记得a数组是b数组的前缀和数组比如对b数组的b[i]的修改会影响到a数组中从a[i]及往后的每一个数。首先让差分b数组中的b[l] c,通过前缀和运算a数组变成 a[l] c ,a[l1] c,,,,,, a[n] c;然后我们打个补丁b[r1] - c, 通过前缀和运算a数组变成 a[r1] - c,a[r2] - c,,,,,,,a[n] - c;为啥还要打个补丁我们画个图理解一下这个公式的由来:b[l] c效果使得a数组中a[l]及以后的数都加上了c(红色部分)但我们只要求l到r区间加上c, 因此还需要执行b[r1] - c,让a数组中a[r1]及往后的区间再减去c(绿色部分)这样对于a[r]以后区间的数相当于没有发生改变。因此我们得出一维差分结论给a数组中的[ l, r]区间中的每一个数都加上c,只需对差分数组b做b[l] c,b[r1] - c。时间复杂度为O(1), 大大提高了效率。总结题目练习 AcWing 797. 差分输入一个长度为n的整数序列。接下来输入m个操作每个操作包含三个整数l, r, c表示将序列中[l, r]之间的每个数加上c。请你输出进行完所有操作后的序列。输入格式第一行包含两个整数n和m。第二行包含n个整数表示整数序列。接下来m行每行包含三个整数lrc表示一个操作。输出格式共一行包含n个整数表示最终序列。数据范围1≤n,m≤100000,1≤l≤r≤n,−1000≤c≤1000,−1000≤整数序列中元素的值≤1000输入样例6 31 2 2 1 2 11 3 13 5 11 6 1输出样例3 4 5 3 4 2AC代码12345678910111213141516171819202122232425262728//差分 时间复杂度 o(m)#includeiostreamusingnamespacestd;constintN1e510;inta[N],b[N];intmain(){intn,m;scanf(%d%d,n,m);for(inti1;in;i){scanf(%d,a[i]);b[i]a[i]-a[i-1];//构建差分数组}intl,r,c;while(m--){scanf(%d%d%d,l,r,c);b[l]c;//表示将序列中[l, r]之间的每个数加上cb[r1]-c;}for(inti1;in;i){b[i]b[i-1];//求前缀和运算printf(%d ,b[i]);}return0;}6、二维差分如果扩展到二维我们需要让二维数组被选中的子矩阵中的每个元素的值加上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数组类比一维差分我们执行以下操作来使被选中的子矩阵中的每个元素的值加上cb[x1][y1] c;b[x1,][y21] - c;b[x21][y1] - c;b[x21][y21] c;每次对b数组执行以上操作等价于123for(intix1;ix2;i)for(intjy1;jy2;j)a[i][j]c;我们画个图去理解一下这个过程b[x1][ y1 ] c; 对应图1 ,让整个a数组中蓝色矩形面积的元素都加上了c。b[x1,][y21]-c; 对应图2 ,让整个a数组中绿色矩形面积的元素再减去c使其内元素不发生改变。b[x21][y1]- c; 对应图3 ,让整个a数组中紫色矩形面积的元素再减去c使其内元素不发生改变。b[x21][y21]c; 对应图4,让整个a数组中红色矩形面积的元素再加上c红色内的相当于被减了两次再加上一次c才能使其恢复。我们将上述操作封装成一个插入函数:1234567voidinsert(intx1,inty1,intx2,inty2,intc){//对b数组执行插入操作等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了cb[x1][y1]c;b[x21][y1]-c;b[x1][y21]-c;b[x21][y21]c;}我们可以先假想a数组为空那么b数组一开始也为空但是实际上a数组并不为空因此我们每次让以(i,j)为左上角到以(i,j)为右上角面积内元素(其实就是一个小方格的面积)去插入ca[i][j]等价于原数组a中(i,j)到(i,j)范围内 加上了a[i][j],因此执行n*m次插入操作就成功构建了差分b数组.这叫做曲线救国。代码如下1234567for(inti1;in;i){for(intj1;jm;j){insert(i,j,i,j,a[i][j]);//构建差分数组}}复制讲解当然关于二维差分操作也有直接的构造方法公式如下b[i][j]a[i][j]−a[i−1][j]−a[i][j−1]a[i−1][j−1]二维差分数组的构造同一维差分思维相同因次在这里就不再展开叙述了。总结题目练习 AcWing 798. 差分矩阵输入一个n行m列的整数矩阵再输入q个操作每个操作包含五个整数x1, y1, x2, y2, c其中(x1, y1)和(x2, y2)表示一个子矩阵的左上角坐标和右下角坐标。每个操作都要将选中的子矩阵中的每个元素的值加上c。请你将进行完所有操作后的矩阵输出。

相关文章:

通俗易懂的C++前缀和与差分算法图文示例详解

1、前缀和 前缀和是指某序列的前n项和,可以把它理解为数学上的数列的前n项和,而差分可以看成前缀和的逆运算。合理的使用前缀和与差分,可以将某些复杂的问题简单化。 2、前缀和算法有什么好处? 先来了解这样一个问题&#xff1a…...

C++中如何调用C语言的代码实现

为什么要是用 extern "C"在进行C开发的时候,由于C、C编译规则是不同的。C编译函数方法是 使用mangle的技术 。123456789101112void func(int age) {}void func(int age, int height) {}/*如果有这两个函数要被调用,在C语言中函数重载是不允许的…...

别再折腾内网穿透了!用EC600N 4G模块+华为云IoTDA,5分钟搞定远程宠物定位数据上传

5分钟实现宠物定位数据上云:EC600N 4G模块与华为云IoTDA实战指南 当你的宠物突然从视线中消失时,那种焦虑感是任何宠物主人都深有体会的。传统的蓝牙防丢器仅有几十米的有效范围,而GPS定位器又常受限于复杂的网络配置。现在,通过…...

别再硬刚滑块了!一个Python脚本自动搞定淘宝X5SEC验证码

Python自动化破解淘宝X5SEC滑块验证码实战指南 淘宝作为国内最大的电商平台之一,其反爬机制一直处于行业领先水平。其中X5SEC滑块验证码是淘宝用来识别自动化程序的主要手段之一。对于需要批量采集商品数据或进行价格监控的开发者来说,频繁的手动滑块验证…...

pyperclip测试策略:如何确保跨平台剪贴板功能的稳定性

pyperclip测试策略:如何确保跨平台剪贴板功能的稳定性 【免费下载链接】pyperclip Python module for cross-platform clipboard functions. 项目地址: https://gitcode.com/gh_mirrors/py/pyperclip pyperclip是一个强大的Python跨平台剪贴板模块&#xff0…...

CircularProgressBar扩展开发:如何基于现有库创建自定义进度条组件

CircularProgressBar扩展开发:如何基于现有库创建自定义进度条组件 【免费下载链接】CircularProgressBar Create circular ProgressBar in Android ⭕ 项目地址: https://gitcode.com/gh_mirrors/ci/CircularProgressBar CircularProgressBar是一个功能强大…...

Haneke与AFNetworking集成实战:构建强大的iOS图片加载系统

Haneke与AFNetworking集成实战:构建强大的iOS图片加载系统 【免费下载链接】Haneke A lightweight zero-config image cache for iOS, in Objective-C. 项目地址: https://gitcode.com/gh_mirrors/ha/Haneke 在iOS应用开发中,图片加载与缓存是影响…...

ESJsonFormat-Xcode泛型支持:Xcode 7及以上版本的优化特性

ESJsonFormat-Xcode泛型支持:Xcode 7及以上版本的优化特性 【免费下载链接】ESJsonFormat-Xcode 将JSON格式化输出为模型的属性 项目地址: https://gitcode.com/gh_mirrors/es/ESJsonFormat-Xcode 如果你是一位iOS开发者,那么你一定遇到过将JSON数…...

全新UI 阅后即焚V2正式版系统源码_全开源_安全加密传输

概述 在数字化信息交流日益频繁的今天,如何安全、私密地传输敏感数据(如商业机密、登录凭证、个人隐私)已成为企业和个人用户共同面临的严峻挑战。传统的即时通讯工具往往存在聊天记录留存、云端备份等安全隐患,难以满足“阅后即…...

3分钟搞定B站视频下载:免费解锁4K大会员高清视频的完整教程

3分钟搞定B站视频下载:免费解锁4K大会员高清视频的完整教程 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 你是否曾为无法…...

从零到一:用面包板和晶体管手搓一个4bit加法器(附完整电路图与避坑指南)

从零到一:用面包板和晶体管手搓一个4bit加法器(附完整电路图与避坑指南) 深夜的实验室里,面包板上横七竖八地插着几十个三极管和电阻,当我第三次测量到错误的输出电平时,终于意识到——这个看似简单的4bit加…...

【免费下载】 Maven 3.8.5 压缩包下载【maven下载安装与配置】

Maven 3.8.5 压缩包下载 简介 本仓库提供 Maven 3.8.5 版本的压缩包下载。Maven 是一个强大的项目管理和构建自动化工具,广泛应用于 Java 项目的开发中。 资源文件 文件名: maven3.8.5压缩包描述: Maven 3.8.5 版本的压缩包 下载链接 请点击以下链接下载 Mave…...

Bilibili-Evolved:打造无网络依赖的哔哩哔哩增强体验技术解析

Bilibili-Evolved:打造无网络依赖的哔哩哔哩增强体验技术解析 【免费下载链接】Bilibili-Evolved 强大的哔哩哔哩增强脚本 项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved 在当今网络环境复杂多变的时代,用户对Web应用的稳定性要…...

从虚拟机到私有云:手把手教你用VirtualBox+CentOS 7搭建个人OpenStack学习环境

从虚拟机到私有云:手把手教你用VirtualBoxCentOS 7搭建个人OpenStack学习环境 在个人电脑上搭建OpenStack环境听起来像是企业级IT工程师的专属领域,但事实上,借助VirtualBox这样的免费虚拟化工具和CentOS 7的稳定性,任何人都可以在…...

手把手拆解FD-SOI工艺流程:从SOI衬底到应变硅外延的保姆级图解

从SOI衬底到应变硅外延:FD-SOI工艺全流程拆解指南 想象一下建造一座微型城市,每一栋建筑只有头发丝直径的万分之一大小。这就是FD-SOI工艺工程师的日常工作——在硅片上用原子级精度"建造"晶体管。与传统的体硅工艺不同,FD-SOI&…...

垃圾分类助手APP - 安卓期末大作业

垃圾分类助手APP - 安卓期末大作业 【下载地址】垃圾分类助手APP-安卓期末大作业 本项目是一个基于Android Studio的安卓应用程序,专为满足垃圾分类指导需求设计。作为一款学习与实践相结合的期末大作业,它不仅集成了丰富的前端和后端功能,还…...

实战复盘:我们如何定位并彻底解决Spring Gateway的‘262144字节’缓冲区限制问题

深度解析:Spring Gateway缓冲区限制问题的工程化解决方案 1. 问题背景与现象分析 去年夏天,我们的电商平台在促销活动期间突然遭遇了一系列诡异的API请求失败。前端团队报告称,部分包含大型商品列表的JSON请求在通过Spring Cloud Gateway时被…...

用STM32F103C8T6做个触摸感应示波器?手把手教你ADC采集+OLED波形显示(附完整代码)

用STM32F103C8T6打造触摸感应示波器:从ADC采集到OLED波形显示的趣味实践 在嵌入式开发领域,将枯燥的技术参数转化为可视化的交互体验,往往能激发学习者的深层兴趣。今天我们要实现的,不仅是一个简单的信号采集系统,而是…...

别再手动挖洞!3DMAX QuickBoolean插件保姆级安装与工具栏配置指南(附图标含义详解)

3DMAX QuickBoolean插件:从零开始的高效布尔运算实战指南 在三维建模领域,布尔运算一直是创建复杂几何形状的必备技能。无论是建筑可视化中的门窗开洞,还是工业设计中的零件装配,传统布尔运算操作往往伴随着繁琐的步骤和不可预测的…...

【免费下载】 探索双面神技:STM32G474的USB跨界应用

探索双面神技:STM32G474的USB跨界应用 在物联网与嵌入式开发的世界里,寻找一款能兼顾数据传输与控制沟通的神器是每个开发者的心头好。今天,我们就来揭秘这样一个宝藏项目——STM32G474实现USB的MSCCDC组合功能,它巧妙地将STM32G4…...

如何轻松备份微信聊天记录:WeChatMsg完全免费的数据守护方案

如何轻松备份微信聊天记录:WeChatMsg完全免费的数据守护方案 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we…...

【Android】CloneTTS最强朗读听书引擎-可克隆一切音色

【Android】CloneTTS最强朗读听书引擎-可克隆一切音色 链接:https://pan.xunlei.com/s/VOsu4mh3O_d7zjeERkKPfcG4A1?pwddi3y# CloneTTS 是一款运行在安卓系统本地的文字转语音(TTS)原生引擎,允许用户离线克隆所需的声音并直接使用该声音来朗读书籍或长…...

双核Delfino架构解析:如何解决复杂实时控制系统的性能瓶颈

1. 项目概述:从“双核”到“创新架构”的深度解构最近在和一些做工业控制、新能源以及高端医疗器械的朋友交流时,发现一个词被反复提及,那就是“双核Delfino”。乍一听,这像是一个具体的芯片型号,但深入聊下去&#xf…...

工作流的常见模式 [ 2 ]

协调者 - 工作者模式(Orchestrator-Workers)概念好,我们接下来继续来看第4种工作模式。第4种工作模式呢它叫协调者工作者模式。什么是协调者和工作者模式呢?跟大家讲解这个模式,我们需要结合实际当中的例子&#xff0c…...

让旧款iPhone/iPad重获新生:Legacy-iOS-Kit终极使用指南

让旧款iPhone/iPad重获新生:Legacy-iOS-Kit终极使用指南 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to restore/downgrade, save SHSH blobs, jailbreak legacy iOS devices, and more 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit …...

从新手到认证专家:NotebookLM总结能力跃迁路径图(含Google官方未公开的评估矩阵V2.1)

更多请点击: https://intelliparadigm.com 第一章:NotebookLM总结能力跃迁路径总览 NotebookLM 是 Google 推出的面向研究者与开发者的情境化 AI 助手,其核心突破在于将用户上传的文档(PDF、TXT、Google Docs)转化为可…...

10个必须知道的simplex-noise.js实战技巧:从基础到高级应用

10个必须知道的simplex-noise.js实战技巧:从基础到高级应用 【免费下载链接】simplex-noise.js A fast simplex noise implementation in Javascript / Typescript. 项目地址: https://gitcode.com/gh_mirrors/si/simplex-noise.js simplex-noise.js是一个快…...

5分钟搭建拼多多数据采集系统:零基础也能掌握的电商数据分析利器

5分钟搭建拼多多数据采集系统:零基础也能掌握的电商数据分析利器 【免费下载链接】scrapy-pinduoduo 拼多多爬虫,抓取拼多多热销商品信息和评论 项目地址: https://gitcode.com/gh_mirrors/sc/scrapy-pinduoduo 想要了解拼多多平台的热销商品趋势…...

5步掌握代码绘图:Draw.io Mermaid插件高效指南

5步掌握代码绘图:Draw.io Mermaid插件高效指南 【免费下载链接】drawio_mermaid_plugin Mermaid plugin for drawio desktop 项目地址: https://gitcode.com/gh_mirrors/dr/drawio_mermaid_plugin 还在为技术文档中的图表绘制而烦恼吗?每次需求变…...

独立开发者如何借助Taotoken多模型能力优化个人项目成本

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者如何借助Taotoken多模型能力优化个人项目成本 对于独立开发者和小型项目而言,在探索大模型应用时&#xff0…...