这段代码的核心思路是利用差分数组来高效处理区间更新操作,并最终恢复数组的值。差分数组是一种非常高效的数据结构,特别适合处理频繁的区间加法操作。以下是代码的详细思路解析:
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
运行过程:
-
输入数组长度
n = 5
和操作次数m = 3
。 -
输入数组
a = [1, 2, 3, 4, 5]
。 -
初始化差分数组
b
:-
b = [1, 1, 1, 1, 1, 0]
(初始值为原数组的差分值)。
-
-
执行操作:
-
操作 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]
。
-
-
恢复原数组:
-
b = [3, 7, 9, 5, 7]
。
-
-
输出结果:
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;
}
的场景。