蓝桥杯C++基础算法-差分

这段代码的核心思路是利用差分数组来高效处理区间更新操作,并最终恢复数组的值。差分数组是一种非常高效的数据结构,特别适合处理频繁的区间加法操作。以下是代码的详细思路解析:


1. 问题背景

假设有一个数组 a,长度为 n,我们需要对数组的某个区间 [l, r] 进行加法操作,即将区间 [l, r] 内的所有元素增加一个常数 c。直接对每个区间进行操作会导致每次操作的时间复杂度为 O(n),效率较低。为了优化区间更新操作,可以使用差分数组技术。


2. 差分数组的概念

差分数组 b 是一个辅助数组,其中 b[i] 表示原数组 a 中从第 i 个元素到第 i+1 个元素的变化量。通过差分数组,可以高效地完成区间加法操作:

  • 对区间 [l, r] 增加 c,只需要在差分数组中进行两次操作:

    • b[l] += c:表示从第 l 个元素开始增加 c

    • b[r + 1] -= c:表示从第 r + 1 个元素开始减少 c,以抵消前面的增加操作。

通过这种方式,每次区间更新操作的时间复杂度为 O(1)


3. 代码逻辑解析

(1) 输入部分
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
  • 用户输入数组的长度 n 和操作次数 m

  • 接着输入数组 a 的每个元素。数组 a 的索引从 1 开始,方便后续计算。

(2) 差分数组的初始化
for (int i = 1; i <= n; i++) insert(i, i, a[i]);
  • 使用 insert 函数将原数组 a 的每个元素初始化到差分数组 b 中。

  • 对于每个 a[i],调用 insert(i, i, a[i]),将 a[i] 的值加到 b[i] 上。

  • 这一步实际上是将原数组 a 转换为差分数组 b

(3) 区间更新操作
while (m--)
{
    int l, r, c;
    cin >> l >> r >> c;
    insert(l, r, c);
}
  • 用户输入操作的区间 [l, r] 和增加值 c

  • 调用 insert 函数对差分数组 b 进行更新:

    • b[l] += c:从第 l 个元素开始增加 c

    • b[r + 1] -= c:从第 r + 1 个元素开始减少 c,以抵消前面的增加操作。

(4) 恢复原数组
for (int i = 1; i <= n; i++) b[i] += b[i - 1];
  • 通过差分数组 b 恢复最终的数组值:

    • b[i] += b[i - 1]:将差分数组的值累加到当前元素上,恢复原数组的值。

    • 这一步实际上是将差分数组 b 转换回原数组。

(5) 输出结果
for (int i = 1; i <= n; i++) cout << b[i] << ' ';
  • 输出最终的数组值,每个元素之间用空格分隔。


4. 代码效率分析

  • 时间复杂度

    • 初始化差分数组的时间复杂度为 O(n)

    • 每次区间更新操作的时间复杂度为 O(1)

    • 恢复原数组的时间复杂度为 O(n)

    • 总时间复杂度为 O(n + m),其中 n 是数组长度,m 是操作次数。

  • 空间复杂度

    • 使用了一个额外的差分数组 b,空间复杂度为 O(n)


5. 示例运行

输入:
5 3
1 2 3 4 5
1 3 2
2 4 3
3 5 1
运行过程:
  1. 输入数组长度 n = 5 和操作次数 m = 3

  2. 输入数组 a = [1, 2, 3, 4, 5]

  3. 初始化差分数组 b

    • b = [1, 1, 1, 1, 1, 0](初始值为原数组的差分值)。

  4. 执行操作:

    • 操作 1:insert(1, 3, 2)b = [3, 1, 1, -1, 1, 0]

    • 操作 2:insert(2, 4, 3)b = [3, 4, 1, -4, 1, 0]

    • 操作 3:insert(3, 5, 1)b = [3, 4, 2, -4, 2, 0]

  5. 恢复原数组:

    • b = [3, 7, 9, 5, 7]

  6. 输出结果:

    3 7 9 8 6

6. 总结

这段代码的核心思路是通过差分数组技术,将区间更新操作的时间复杂度从 O(n) 优化到 O(1)。通过预先计算一个差分数组 b,可以高效地完成多次区间加法操作,并在最后通过累加恢复原数组的值。这种方法特别适用于需要频繁对数组区间进行加法操作

#include<bits/stdc++.h>
using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N];

void insert(int l, int r, int c)
{
	b[l] += c;
	b[r + 1] -= c;
} 


int main()
{
	cin>>n>>m;
	for(int i = 1; i <= n; i ++)
		cin >> a[i];
	for(int i = 1; i <= n; i ++)
		insert(i, i, a[i]);
	while(m --)
	{
		int l, r, c;
		cin>>l>>r>>c;
		insert(l, r, c);
	}
	for(int i = 1; i <= n; i ++)
		b[i] += b[i - 1];
	for(int i = 1; i <= n; i ++)
		cout<<b[i]<<' ';
	return 0;

} 

的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值