【算法通关指南:算法基础篇(三)】一维差分专题:1.【模板】差分 2.海底高铁

🔥小龙报:个人主页

🎬作者简介:C++研发,嵌入式,机器人方向学习者

❄️个人专栏:《算法通关指南》
永远相信美好的事情即将发生


文章目录


前言

本专栏聚焦算法题实战,系统讲解算法模块:以《c++编程》,《数据结构和算法》《基础算法》《算法实战》 等几个板块以题带点,讲解思路与代码实现,帮助大家快速提升代码能力
ps:本章节题目分两部分,比较基础笔者只附上代码供大家参考,其他的笔者会附上自己的思考和讲解,希望和大家一起努力见证自己的算法成长


一、差分

前缀和与差分的核心思想是预处理,可以在暴力枚举的过程中,快速给出查询的结果,从而优化时间复杂度,是经典的用空间替换时间的做法。
本质前缀和与差分是⼀对互逆的运算

二、一维差分

2.1 差分数组构建方式

根据定义f[i]=a[i]−a[i−1]
根据差分数组的性质f[i] += a[i], f[i+1] −= a[i]

2.2 根据差分数组的性质处理区间修改

核心公式f[L] + = c, f[R+1] − = c

2.3 还原数组

对差分数组做⼀次「前缀和」,就可以还原出原数组

三、一维差分经典算法题

3.1【模板】差分

3.1.1题目

链接:【模板】差分

3.1.2 算法原理

依照刚才讲解一维差分原理模拟即可

3.1.3代码

3.1.3.1 根据差分数组的性质

c 复制代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int f[N];
int main()
{
	cin >> n >> m;

	for (int i = 1; i <= n; i++)
	{
		int x;
		cin >> x;

		f[i] += x;
		f[i + 1] -= x;
	}
	while (m--)
	{
		int l, r, k;
		cin >> l >> r >> k;
		f[l] += k;
		f[r + 1] -= k;
	}

	for (int i = 1; i <= n; i++)
	{
		f[i] += f[i - 1];
		cout << f[i] << " ";
	}

	return 0;
}

3.1.3.2 根据定义

c 复制代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int n, m;
int f[N];
int a[N];
int main()
{
	cin >> n >> m;

	for (int i = 1; i <= n; i++)
		cin >> a[i];

	for (int i = 1; i <= n; 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;
	}

	for (int i = 1; i <= n; i++)
	{
		f[i] += f[i - 1];
		cout << f[i] << " ";
	}

	return 0;
}

3.2 海底高铁

3.2.1题目

链接:海底高铁

3.2.2 算法原理

1.先考虑如何让花费最小,想要求最小花费,需要知道每⼀段高铁被「乘坐了多少次」,记作f[i],那么最小花费就是「买票的花费」与「买卡的花费」两者之间的最小值:f[i]

(1)买票花费:;a[i]×f[i]

(2)买卡花费,乘车花费+工本费:b[i]×f[i]+c[i]

(3)那么最小花费就是:mincost=min(a[i]×f[i], b[i]×f[i]+c[i])

2.接下来考虑如何求出每⼀段⾼铁被「乘坐了多少次」。根据访问城市的序列p1 ,p2 ,p3 ,...,pm 可知,对于任意⼀次访问 pi∼p ,我们会乘坐[pi ~ pi + 1 - 1]之间所有的高铁,比如p =i 3, pi+1 = 6,那么[3,5]之间所有的高铁都会被乘坐⼀次,相当于每个数都加上1,「注意6位置不会乘坐到」。那么我们就可以利用「差分数组」

(1)创建⼀个全为0的差分数组;

(2)遍历访问序列,对于每⼀次访问f[p]+ i +, f[p]− i+1 −

(3)然后对差分数组做⼀次前缀和,就得到每个⾼铁乘坐的次数

注意城市访问的序列有可能pi > pi + 1,此时应该「交换」⼀下顺序

3.2.3代码

c 复制代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL f[N];

int main()
{
	LL n, m;
	cin >> n >> m;

	LL x;
	cin >> x;
	for (int i = 2; i <= m; i++)
	{
		LL y;
		cin >> y;

		// x -> y
		if (y > x)
		{
			f[x]++;
			f[y]--;
		}

		// y -> x
		else
		{
			f[x]--;
			f[y]++;
		}
		x = y;
	}

	for (int i = 1; i < n; i++)
		f[i] += f[i - 1];

	LL ret = 0;
	for (int i = 1; i < n; i++)
	{
		LL a, b, c;
		cin >> a >> b >> c;
		ret += min(a * f[i], c + b * f[i]);
	}

	cout << ret << endl;
	return 0;

}

总结与每日励志

摘要: 本文介绍了差分算法的基本原理及其应用,重点讲解了一维差分的构建方式、区间修改处理及数组还原方法。通过经典算法题如【模板】差分和海底高铁问题,展示了差分在优化时间复杂度中的实际应用。文章还提供了详细的代码实现,帮助读者快速掌握差分算法。最后以励志语句"永远相信美好的事情即将发生"鼓励读者坚持学习与成长。 关键词: 差分算法、前缀和、区间修改、时间复杂度、算法实战

相关推荐
白书宇4 小时前
【STM32实战】从零开始写Linux 0.12内核 第1个实验安装IAR 8.5
linux·c语言·驱动开发·stm32·单片机·嵌入式硬件
AndrewHZ5 小时前
【复杂网络分析】如何入门Louvain算法?
python·算法·复杂网络·社区发现·community det·louvain算法·图挖掘
AndrewHZ5 小时前
【图像处理基石】如何基于黑白图片恢复出色彩?
图像处理·深度学习·算法·计算机视觉·cv·色彩恢复·deoldify
lengjingzju5 小时前
一网打尽Linux IPC(四):POSIX IPC
linux·服务器·c语言
POLITE35 小时前
Leetcode 3.无重复字符的最长子串 JavaScript (Day 4)
javascript·算法·leetcode
城东米粉儿5 小时前
Dynamic Feature Modules 笔记
android
无言Echo5 小时前
Android 高斯模糊(1) 窗口模糊及java侧基本流程简述
android
Xの哲學5 小时前
Linux IPC机制深度剖析:从设计哲学到内核实现
linux·服务器·网络·算法·边缘计算
无言Echo5 小时前
Android 高斯模糊(2)BackgroundBlurDrawable使用及相关Bug
android
sin_hielo5 小时前
leetcode 756(枚举可填字母)
算法·leetcode