完整教程:基础算法---【差分】

news/2025/9/25 17:23:41/文章来源:https://www.cnblogs.com/lxjshuju/p/19111617

题目一:【模板】一维差分

https://ac.nowcoder.com/acm/problem/226303

解题思路

        差分就是帮助我们解决"某一个区间统一加上(减去)某一个数"这类问题的。本题第一步先预处理出一个差分数组,假设差分数组的名字为f,f[i]就表示题给数组的当前元素与前一个元素的差值,即为a[i]-a[i-1]。第二步就是利用差分数组来解决区间统一加k的操作,这里有一个性质,如果我们要对[l,r]区间里边的每一个数都加上一个数,其实仅需要将f[l] += k,对f[r + 1] -= k,就可以了,请看下图的推导。

        经过对f数组的操作,其实就实现了区间加k的操作,但是这仅仅是对f数组进行了操作,意思就是我对a数组的[l,r]区间进行了统一+k操作之后对f数组的改变我已经完成了,但题目要的是a数组区间+k之后的结果,所以第三步就是还原出a数组,其实只要对f数组执行前缀和操作就可以了,看下图。

代码实现

#include
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL a[N];
//注意:这里的f数组也可以直接利用差分数组的定义来实现(此时就不需要原始数组a了)
//在最一开始的时候可以理解为f数组里边的元素全都是0,而a数组也全都是0
//当读入a[i]的时候,就相当于对区间[i,i]执行了+a[i]的操作,所以可以直接利用差分数组的性质来创建差分数组
//即为 f[i] += a[i] f[i + 1] -= a[i];
LL f[N];//差分数组
int n, m;
int main()
{
cin >> n >> m;
for (int i = 1; i > a[i];
f[i] = a[i] - a[i - 1];
}
while (m--)
{
int l, r, k;
cin >> l >> r >> k;
f[l] += k;
f[r + 1] -= k;
}
//还原数组a
for (int i = 1; i <= n; i++)
{
a[i] = a[i - 1] + f[i];
cout << a[i] << " ";
}
return 0;
}

        注意事项:差分数组在使用的时候必须要所有操作全部操作完成之后才能还原出操作之后的数组,其实就是前缀和数组。有些题目会多次输入输出,此时如果用差分来做就会导致时间复杂度过高。

题目二:海底高铁

https://www.luogu.com.cn/problem/P3406

解题思路

        题目的意思就是总共N个城市,Uim要去M个地方,需要我们输出最少花费,那么我们根据题意,每经过相邻的两个城市可能的花费就是要么直接花A元买车票,要么就是先用C元买一张IC卡,然后再用B元买车票,总计C+B元。我们可以将Uim要去的所有城市都看成一小段(就是每两个城市之间看成一段),计算出每一段他经过的次数,假设为k,要求的是最小的花费,仅需要min(Ak,C+Bk),这样就得到了该段的最小花费,最后将所有段的最小花费累加起来就是结果。

        如何计算经过i段的次数呢?每次乘车,都可以看作是区间 [l,r] 里边的每一个元素+1,这就可以直接用差分来计算了(相当于模板题里边的修改差分数组),请看下图(图片中的f数组就是差分数组)。

代码实现

#include
using namespace std;
typedef long long LL;
const int N = 1E5 + 10;
LL f[N];//本题采用直接计算差分数组的方式
int n, m;
int main()
{
cin >> n >> m;
int l;
cin >> l;//标记区间左边的元素
for(int i = 2;i > r;
//第一个if就表示区间大小有问题,不能用swap,因为用了swap就找不到 l 了,直接反过来计算就可以了。
if (l > r)
{
f[r]++;
f[l]--;
}
else
{
f[l]++;
f[r]--;
}
l = r;//更新区间新的左值
}
//还原数组(数组里边的值就表示每段经过的次数)---前缀和
for (int i = 1; i > a >> b >> c;
ret += min(a * f[i], c + b * f[i]);
}
cout << ret << endl;
return 0;
}

题目三:二维差分

https://ac.nowcoder.com/acm/problem/226337

解题思路

        在解决这道题目之前,我们先来探究一下二维差分数组的性质。请看下图。

        我们要知道,差分数组通过前缀和运算是可以还原出子矩阵统一+k之后的结果矩阵的。

        现对[x1,y1]~[x2,y2]的a数组部分统一执行+k操作。(如上图所示)

        假设我们在f数组[x1,y1]坐标位置处+k,就会导致以[x1,y1]为左上角的所有元素的前缀和都+k(即蓝色框出的部分)对于红色方框内的部分来说,前缀和+k的结果正是我们想要的,但是对于在蓝色方框内但不在红色方框内的部分,我们不需要它们+k,因此,需要对[x1,y2+1]和[x2+1,y1]这两个坐标内的元素执行-k操作,这样就可以让以它们为左上角的矩阵里边的所有元素不发生改变(即黄色框出部分),但是阴影部分的元素很显然在计算前缀和的时候多减了一个k,所以我们还需要在[x2+1,y2+1]的地方+k。

        知道了二维差分数组的性质之后,对于本道题,第一步先预处理出一个差分数组,每读入一个元素,就相当于是在a数组的[i,j]~[i,j]区间位置实现了一个+k的效果,那么根据二维差分数组的性质,我们就可以直接预处理出一个差分数组。接着就可以执行m次操作了,还是利用二维差分的性质。最后就是利用前缀和还原出区间+k之后的数组。

代码实现

#include
using namespace std;
typedef long long LL;
const int N = 1010;
LL f[N][N];
int n, m, q;
int main()
{
cin >> n >> m >> q;
//预处理差分数组----下边也可以将二维差分的性质封装成一个函数
for (int i = 1; i > x;
f[i][j] += x;
f[i][j + 1]  -= x;
f[i + 1][j] -= x;
f[i + 1][j + 1]  += x;
}
}
//q次操作
while (q--)
{
int x1, y1, x2, y2, k;
cin >> x1 >> y1 >> x2 >> y2 >> k;
f[x1][y1] += k;
f[x1][y2 + 1] -= k;
f[x2 + 1][y1] -= k;
f[x2 + 1][y2 + 1] += k;
}
//前缀和操作
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + f[i][j];
cout << f[i][j] << " ";
}
cout << endl;
}
return 0;
}

题目四:地毯

https://www.luogu.com.cn/problem/P3397

解题思路

        本题基本上就是套用上边的那道模板题目,一共是有m块地毯,每给出一块地毯的坐标就相当于在[x1,y1]~[x2,y2]范围之内所有的值+1,最后利用前缀和还原出”+k“之后的结果数组就可以了。

代码实现

#include
using namespace std;
const int N = 1010;
int f[N][N];
int n, m;
int main()
{
cin >> n >> m;
while (m--)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
f[x1][y1] += 1;
f[x1][y2 + 1] -= 1;
f[x2 + 1][y1] -= 1;
f[x2 + 1][y2 + 1] += 1;
}
//前置和还原
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
f[i][j] = f[i - 1][j] + f[i][j - 1] - f[i - 1][j - 1] + f[i][j];
cout << f[i][j] << " ";
}
cout << endl;
}
return 0;
}

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

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

相关文章

Android 源码中如何生成一个platform JKS 文件?

首先我们需要在源代码环境中将 build/target/product/security/ 文件夹 copy 到本地。 下边的操作需要在 ubuntu 或者 mac 下。重要安全提醒:platform 密钥是系统级私钥,拥有它就能签出系统权限应用。不要把它放到公…

后端面试八股(go 方向)

go 后端面试准备 一、Go语言相关 1、Go里有哪些数据结构是并发安全的?int类型是并发安全的吗?sync 包中的类型sync.Mutex 和 sync.RWMutex:互斥锁,通过加锁机制保证临界区安全 sync.WaitGroup:用于等待一组 gorou…

ArcGIS 不重叠且无缝的拓扑检查和修改

ArcGIS 不重叠且无缝的拓扑检查和修改创建拓扑: 新建数据库→新建dataset→导入要素 dataset右键新建topo 设置容差和规则 拓扑容差: 0.001 默认标准 0.00001 清查标准 注意:容差为分辨率两倍 拓扑规则: 1.不能重…

C++设计模式之创建型模式:工厂方法模式(Factory Method) - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

【铸网-2025】线下赛 web 详细题解

<?php show_source(index.php); class MGkk8 {public $a;public $b;public function rpl2(){echo(MGrp12;);$b = $this->b;if ($this->a == "RPG") {echo(ifyes;);($b->a)($b->b."&quo…

2025/9/25

A 用时:1h 预期:100pts 实际:100pts 发现有两种做法,可以直接模拟,递推,复杂度分别为 \(O(n^2)\),\(O(n^2\log n)\),而递推可以用 bitset 压一下。 考虑根号分治复杂度为 \(O(B \times n+\frac{n^2\times log …

唐山市政建设总公司网站重庆装修设计公司排名

181/2461/8938产品概述 R&S SMU200A信号发生器旨在满足现代通信系统研发及其生产中遇到的所有要求。R&S SMU200A矢量信号发生器不仅将多达两个独立的信号发生器组合在一个只有四个高度单位的机柜中&#xff0c;还提供无与伦比的RF和基带特性。 Rohde & Schwarz S…

为什么要建设档案网站个人网页设计思路流程内容

142873-41-4脂质过氧化抑制剂1 英文名称&#xff1a;Lipid peroxidation inhibitor 1 中文名称&#xff1a;脂质过氧化抑制剂 化学名称&#xff1a;2,4,6,7-四甲基-2-[(4-苯基哌啶-1-基)甲基]-3H-1-苯并呋喃-5-胺 CAS&#xff1a;142873-41-4 外观&#xff1a;固体粉末 分…

网站建设 云南如何布局网站

标题链接【RM2021 四川站第二期直播】步兵设计及弹道测试https://bbs.robomaster.com/forum.php?modviewthread&tid11504&extrapage%3D1%26filter%3Dtypeid%26orderby%3Ddateline【RM2021 黑龙江站第4期直播】步兵机械设计入门2https://bbs.robomaster.com/forum.php?…

读书笔记:揭开索引的两个常见误区

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。本文为个人学…

国标GB28181平台EasyGBS如何赋能路网数字化管理与应急指挥?

国标GB28181平台EasyGBS如何赋能路网数字化管理与应急指挥?随着智慧交通建设的深入,海量、异构的道路监控设备如何实现统一接入、低延迟调阅与智能分析成为关键挑战。本文探讨基于GB/T28181国家标准的EasyGBS视频平台…

完整教程:Spring Boot 核心注解分类与应用指南

完整教程:Spring Boot 核心注解分类与应用指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

分布式数据库迁移OceanBase——基于网易云音乐自研CDC服务的平滑迁移方案

分布式数据库迁移OceanBase——基于网易云音乐自研CDC服务的平滑迁移方案网易云音乐在大体量的业务数据背后,是何种技术方案在支撑?本文分享网易云音乐PB级分库分表架构向原生分布式数据库架构迁移的技术优化经验。编…

获取用户ip所在城市

整体流程图获取当前登录用户所在城市,是一个非常常见的需求,在很多业务场景中用到。 比如:导航的定位功能默认选择的城市,或者一些防盗系统中识别用户两次登录的城市不一样的会有报警提示。 下载geoip2数据库 geoi…

郑州市网站建设公司石河子规划建设局网站

文章目录 &#x1f4d6; 前言1. 认识URL && 引入http协议2. http协议格式2.1 宏观格式&#xff1a;2.2 实验演示&#xff1a; 3. http的方法3.1 GET方法&#xff1a;3.2 POST方法&#xff1a;3.3 GET vs POST&#xff1a; 4. HTTP的报头和状态码5. http的cookie5.1 htt…

电商外贸网站建设新网域名自助管理平台

ANSYS Fluent和COMSOL Multiphysics以及OpenFOAM这3款CFD软件哪个好&#xff1f;cfd软件中哪款最实用&#xff1f;cfd软件有哪些&#xff1f;今天就给大家带来这几款CFD软件对比分析&#xff0c;一起来看看吧。 ANSYS Fluent ANSYS Fluent 是一种流行的计算流体动力学 (CFD) …

【Proteus仿真】AT89C51单片机串行数据转换为并行仿真 - 实践

【Proteus仿真】AT89C51单片机串行数据转换为并行仿真 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Cons…

第13章 day14-15 Webpack逆向

Webpack逆向 Webpack是一个现代的静态模块打包工具,它主要用于前端开发中的模块化打包和构建。通过Webpack,开发者可以将多个模块(包括JavaScript、CSS、图片等)进行打包,生成优化后的静态资源文件,以供在浏览器…

Viper远程配置踩坑记录

尝试etcd做配置中心,就用了Viper。没想到踩了一堆坑,记录一下。 一开始的代码是这么写的,想着先监听再读取: func initViperRemote() {err := viper.AddRemoteProvider("etcd3","http://127.0.0.1:…

深入解析:JVM(六)-- StringTable

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …