前缀和与差分大总结!!!C++

学了忘忘了学o(╥﹏╥)o

题源acwing

  • 讲解前缀和
    • 一维,用于序列
    • 二维,用于矩阵
  • 讲解差分
    • 什么是差分数组?
    • 一维差分数组
    • 二维差分数组
  • 题目一:前缀和
  • 题目二:子矩阵的和
  • 题目三:差分
  • 题目四:差分矩阵

讲解前缀和

什么时候用到前缀和呢?一般题目涉及到数组任意序列或者矩阵的话都有可能考点是前缀和。

一维,用于序列

具体做法:
首先做个预处理,定义一个sum[]数组,sum[i]代表a数组中前i个数的和。
求前缀和运算:

const int N = 1e5+10;
int sum[N], a[N]; //sum[i] = a[1] + a[2] + a[3] ..... a[i];
for(int i = 1; i <= n;i++)
{ sum[i] = sum[i - 1] + a[i];   
}

如果想知道a1…an中任意一段的和,比如 a[l] 到a[r]

 scanf("%d%d", &l, &r);//l是起始,r是终点printf("%d\n", sum[r] - sum[l - 1]);//因为需要包括a[l]

二维,用于矩阵

矩阵的s[i, j]是表示以(1,1)为左上角节点,(i,j)为右下角节点的的矩阵和
在这里插入图片描述
求二维前缀和公式为:
s[i,j] = s[i - 1, j] + s[i, j - 1] - s[i - 1][j - 1] + a[i][j]
所以应用在代码上:

// 求 s[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)为右下角坐标的句子

cout << s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1]

讲解差分

什么是差分数组?

差分一听,啥jb玩意啊,其实就是前缀和倒过来,s是a的前缀和数组,a是s的差分数组

未来的小dream在这里插入图片描述
我本来打算这里简单写的,但是感觉我未来会有忘记的一天,痛定思痛写详细一点o(╥﹏╥)o谁赐我一个过目不忘的脑子

这块注意是,原数组a改动了之后,对应前缀和数组s的变化
假设a数组[3,1,2,5,7],对应s数组是[3,4,6,11,18]
将a[2]加3之后,对应s数组变成[3,4,6+3,11+3,18+3]
再将a[3]减3,对应s数组编程[3,4,6+3,11+3-3,18+3-3]
如下图
在这里插入图片描述
ok,未来的小dream,知道啥意思了吗
总结两点:
原数组单点操作,对应前缀和数组的区间操作
前缀和数组的区间操作,对应原数组的单点操作

这两点之间来回切换思考题目反应要快

次背景下可以有一种题型,题目对a进行多次区间操作,其变化后的a数组!
ok,怎么思考?

对s进行区间操作,之后求a数组,是不是更好求一点,但是题目是对a进行区间操作,怎么办?
可以构造出一个b数组,b数组的前缀和是a数组,现在对a数组进行区间操作,就是对b数组的前缀和数组进行操作,最后将变化后的前缀和数组对应到b上,在从b还原出数组a

简单的说:将对a的区间操作,转换为对b的两点操作,最后由b还原a
这里的b数组就是a的差分数组,

一维差分数组

忘了的再回忆一遍,a是b的前缀和,b是a的差分,a[i][j] = b[1][1] +…+b[i][j]
ok,继续

操作一:给区间[l, r]中的每个数加上c

b[l] += c,b[r + 1] -= c

操作二:知道a数组求b数组

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

二维差分数组

扩展到二维。s[][]是a[][]的前缀和数组,那么a[][]是s[][]的差分数组
假设已经构造好了a[][]。
操作:构建差分数组
相当于在全为0的二维数组加,所以加值都是一样的
现在来执行加的操作

a[x1][y1] += c;
a[x1][y2+1] -= c;
a[x2+1][y1] -= c;
a[x2+1][y2+1] += c

等价于:

for(int i = x1; i <= x2; i ++)for(int j = y1; j <= y2; j ++)s[i][j] += c;

其实也很好理解
在这里插入图片描述
将加法操作封装成一个函数

void insert(int x1,int y1,int x2,int y2,int c)
{     //对a数组执行插入操作//等价于对s数组中的(x1,y1)到(x2,y2)之间的元素都加上了ca[x1][y1]+=c;a[x2+1][y1]-=c;a[x1][y2+1]-=c;a[x2+1][y2+1]+=c;
}

题目一:前缀和

在这里插入图片描述
蛮简单属于前缀和入入入入入入门级题目,只涉及到了序列

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];//保存原数组
int s[N];//保存前缀和数组
int main(){int n, m;cin >> n >> m;for(int i = 1; i <= n; i ++){cin >> a[i];}//开始计算前缀和for(int i = 1; i <= n; i ++){s[i] = s[i - 1] + a[i];}while(m --){int l, r;cin >> l >> r;cout << s[r] - s[l - 1] << endl;}
}

其中需要注意的地方:
a数组也就是原数组,因为s[i]数组的含义是前i个字符和,为了和s[i]对应,a[0]应该初始化为0,当然s[0]也是0

题目二:子矩阵的和

在这里插入图片描述
也是前缀和矩阵的入门级题目了,我这次好好总结,以后再也不忘记了
┭┮﹏┭┮

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int a[N][N];
int 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];}}//计算前缀和s[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];}}while(q --){int x1, y1, x2, y2;cin >> x1 >> y1 >> x2 >> y2;cout << s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1] << endl;}
}

和第一题一样要注意,下标都从1开始

题目三:差分

在这里插入图片描述
首先构造差分数组,接着对应在差分数组上进行两点操作
最后将对应差分数组转化为序列输出
小dream,o(╥﹏╥)o劝你好好学习

很多题解会用a,b数组
我为了和前缀和形成对应还是用s和a数组

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

没有要注意的,小dream多细点心,然后segment fault有可能是因为你数组开的不够大

题目四:差分矩阵

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int s[N][N];
int a[N][N];
void insert(int x1, int y1, int x2, int y2, int c){a[x1][y1] += c;a[x1][y2 + 1] -= c;a[x2 + 1][y1] -= c;a[x2 + 1][y2 + 1] += c;
}
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 >> s[i][j];}}//构建差分数组for(int i = 1; i <= n; i ++){for(int j = 1; j <= m; j ++){insert(i, j, i, j, s[i][j]);}}//对a进行操作while(q --){int x1, y1, x2, y2, c;cin >> x1 >> y1 >> x2 >> y2 >> c;insert(x1, y1, x2, y2, c);}//由a推出s,即可得到答案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];}}for(int i = 1; i <= n; i ++){for(int j = 1; j <= m; j ++){cout << s[i][j] << " ";}cout << endl;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

中电金信:金融机构企业级客户中心建设指南

客户中心系统&#xff08;ECIF​&#xff09;承担了数字化转型的重要使命&#xff0c;管理和认识客户是内部运营和外部监管的共同需求。更为重要的是&#xff0c;客户数据需要全场景地参与到数字化运营中&#xff0c;几乎所有业务都围绕着客户展开&#xff0c;几乎所有场景都需…

无人机技术已应用至地理测绘,Infortrend存储助力测绘数据

--高扩展保存海量无人机数据&#xff0c;高性能支持快速调取建模&#xff0c;数据安全也有免费的备份功能&#xff0c;实实在在好用的存储设备。

KeePass密码管理工具部署

KeePass密码管理工具部署 安装包下载入口 双击执行&#xff0c;根据提示完成安装&#xff1a; 安装完成后如图&#xff1a;

什么是邮件安全证书?如何获取邮件安全证书?

国内药企要想获得GMP认证&#xff0c;除了需满足FDA对药品的审核标准之外&#xff0c;还明文规定需要使用邮件安全证书&#xff08;S/MIME证书&#xff09;与之进行加密邮件沟通。那么什么是邮件安全证书&#xff1f;如何获取邮件安全证书&#xff1f; 什么是邮件安全证书&…

C++ 右值 左值引用

一.什么是左值引用 右值引用 1.左值引用 左值是一个表示数据的表达式(如变量名或解引用的指针)&#xff0c;我们可以获取它的地址可以对它赋值。定义时const修饰符后的左值&#xff0c;不能给他赋值&#xff0c;但是可以取它的地址。左值引用就是给左值的引用&#xff0c;给左…

Java扫码点餐系统奶茶店类型堂食配送小程序源码

&#x1f964;【奶茶新风尚&#xff01;扫码点餐系统&#xff0c;堂食配送两不误】&#x1f964; &#x1f3e0;【堂食新体验&#xff1a;一键下单&#xff0c;即享美味】&#x1f3e0; 踏入心仪的奶茶店&#xff0c;不再需要排队等候点单&#xff0c;只需拿起手机&#xff0…

18730 涂色问题

这个问题可以通过动态规划来解决。我们可以定义一个状态dp[i][j]&#xff0c;表示前i个牛舍中最后一个牛舍的颜色是j的涂色方案数量。然后我们可以通过状态转移方程来更新dp[i][j]。 状态转移方程如下&#xff1a; dp[i][j] dp[i-1][k] (k ! j) 然后我们需要对所有的dp[i][…

【iOS】—— iOS持久化

iOS持久化 1. 数据持久化的目的2. iOS持久化的方案3. 数据持久化方式的分类内存缓存磁盘缓存 4. 沙盒机制5. 沙盒的目录结构获取应用程序的沙盒路径每次编译代码会生成新的沙盒路径&#xff0c;每次运行获得的沙盒路径都不一样。访问沙盒目录常用C函数介绍沙盒目录介绍 6. 持久…

Tomcat IntelliJ IDEA整合

一、下载及安装Tomcat 下载官网&#xff1a;Apache Tomcat - Welcome! 1.点击红色框中的任意一个版本 2.点击下载 3.解压后放在任意路径&#xff08;我的是放在D盘&#xff09; 4.在bin目录下找到startup.bat&#xff0c;点击启动Tomcat 5.如果双击启动后&#xff0c;终端出…

什么是通孔,盲孔,埋孔

通孔&#xff1a;贯穿所有层的孔&#xff0c;容易被逆向破解。 盲孔&#xff1a;表层和内层中间的孔&#xff0c;破解难度加大。 埋孔&#xff1a;内层的孔&#xff0c;破解难度极大。 贯通孔&#xff0c; 浪费了许多宝贵的布线通道&#xff0c;为解决这一矛盾&#xff0c;出…

【综合案例】使用DevEco Studio编写人气卡片

效果展示 知识点 绝对定位 作用&#xff1a;控制组件位置&#xff0c;可以实现层叠效果 特点&#xff1a; 参照 父组件左上角 进行偏移绝对定位后的组件 不再占用自身原有位置 语法&#xff1a;.position(位置对象) 参数&#xff1a;{ x: 水平偏移量 , y: 垂直偏移量} z…

(三)延时任务篇——通过redis的zset数据结构,实现延迟任务实战

前言 在前一篇内容中我们介绍了如何使用redis key过期失效的监控&#xff0c;完成任务延时关闭的功能&#xff0c;同时官方并不支持使用此种方式实现&#xff0c;由于其安全性较低&#xff0c;存在数据丢失的情况。本节内容是对延迟任务的又一实现方案&#xff0c;通过redis z…

多线程上下文切换:详解与优化

多线程上下文切换&#xff1a;详解与优化 一、什么是多线程上下文切换&#xff1f;二、对性能的影响2.1 优点2.2 缺点 三、优化策略 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、什么是多线程上下文切换&#xff1f; 多线程上下文切…

使用pfld模型进行表盘读数检测

目录 1. 下载项目和数据集2. 配置环境3. 训练和测试3.1 训练3.2 测试 4. 参考 使用pfld模型对压力表进行读表检测 1. 下载项目和数据集 下载项目&#xff1a; git clone https://github.com/zhouayi/pfld.git下载数据集&#xff1a; wget https://github.com/zhouayi/pfld/r…

钢琴模拟器

文章目录 钢琴模拟器代码结构HTML结构CSS样式JavaScript功能 源码效果图 钢琴模拟器 代码结构 HTML结构 <html>: HTML文档的根元素。 <head>: 包含文档的元数据。 <base>: 指定相对URL的基准。 <title>: 指定页面的标题。 <style>: 包含嵌入的…

Linux中进程间通信和理解管道

管道文件为内存及文件&#xff0c;没有名称&#xff08;匿名管道&#xff09; 如何让两个进程看到同一个管道文件&#xff1f; 通过fork创建子进程完成。 匿名管道可以用于父子进程之间的通信。 匿名管道是一个固定大小的缓冲区&#xff0c;写端写满后就会阻塞&#xff0c;…

Python自动发送邮件如何设置邮件内容格式?

Python自动发送邮件时&#xff0c;如何自动化发送HTML格式邮件&#xff1f; Python是一种功能强大且灵活的编程语言&#xff0c;广泛用于各种自动化任务&#xff0c;其中包括自动发送邮件。AokSend将介绍在使用Python自动发送邮件时&#xff0c;如何设置邮件内容的格式&#x…

Mongodb集合操作

文章目录 1、进入容器2、如果数据库不存在&#xff0c;则创建数据库&#xff0c;否则切换到指定数据库3、在 MongoDB 中&#xff0c;创建集合不是必须操作。当你插入一些文档时&#xff0c;MongoDB 会自动创建集合。4、查看数据库列表5、查看集合6、显示创建集合7、删除集合 1、…

创新突破 | OpenCSG发布StarShip CodeReview v1.0.0 Beta版

1. 代码审查很关键但耗时耗力 在软件开发过程中&#xff0c;代码审查是确保代码质量的关键环节。代码审查有助于维护代码标准和发现潜在错误&#xff0c;但也常常耗费大量时间和精力。审查者不仅需要深入理解代码逻辑&#xff0c;还要在繁复的逻辑中识别Bug&#xff0c;这个过…

Python_Flask学习笔记

1.配置 查询字符串的形式传参 app.route(/book/list) def book_list():page request.args.get(page,default1,typeint)return f"您获取的是{page}的图书列表&#xff01;"if __name__ __main__:app.run()3.HTML模版渲染 from flask import Flask,render_templa…