差分数组本质就是一个与原数组大小相同的数组,记原数组为arr,差分数组为d,则:
d[i]=arr[i];d[i]=arr[i]-arr[i-1],即原数组对应下标的元素与前一个元素的差。i等于0时,arr[i]=d[i];
i大于0时:
∵
d
[
0
]
=
a
r
r
[
0
]
d
[
1
]
=
a
r
r
[
1
]
−
a
r
r
[
0
]
.
.
.
d
[
i
−
1
]
=
a
r
r
[
i
−
1
]
−
a
r
r
[
i
−
2
]
d
[
i
]
=
a
r
r
[
i
]
−
a
r
r
[
i
−
1
]
∴
a
r
r
[
i
]
=
d
[
0
]
+
d
[
1
]
+
.
.
.
+
d
[
i
]
=
a
r
r
[
i
−
1
]
+
d
[
i
]
∵d[0]=arr[0] \\d[1]=arr[1]-arr[0]\\ ...\\ d[i-1]=arr[i-1]-arr[i-2]\\ d[i]=arr[i]-arr[i-1]\\ ∴arr[i]=d[0]+d[1]+...+d[i]=arr[i-1]+d[i]
∵d[0]=arr[0]d[1]=arr[1]−arr[0]...d[i−1]=arr[i−1]−arr[i−2]d[i]=arr[i]−arr[i−1]∴arr[i]=d[0]+d[1]+...+d[i]=arr[i−1]+d[i]
即:arr[i]为差分数组d[0...i]的前缀和,亦即arr[i-1]+d[i]。
对区间[start, end]统一加上x(x∈R),只需要对d[start]+x, d[end+1]-x
以数组[1, 2, 2, 4, -3, 6]举例:
对区间[1, 4]统一加**-3**,则:

证明:
对
a
r
r
[
s
t
a
r
t
.
.
.
e
n
d
]
+
=
x
∵
d
[
s
t
a
r
t
]
=
a
r
r
[
s
t
a
r
t
]
−
a
r
r
[
s
t
a
r
t
−
1
]
a
r
r
[
s
t
a
r
t
]
+
=
x
,
a
r
r
[
s
t
a
r
t
−
1
]
不变
∴
d
[
s
t
a
r
t
]
+
=
x
又
∵
d
[
e
n
d
+
1
]
=
a
r
r
[
e
n
d
+
1
]
−
a
r
r
[
e
n
d
]
a
r
r
[
e
n
d
]
+
=
x
,
a
r
r
[
e
n
d
+
1
]
不变
∴
d
[
e
n
d
+
1
]
−
=
x
而对于
d
[
s
t
a
r
t
+
1...
e
n
d
]
,我们以
d
[
s
t
a
r
t
+
1
]
为例:
∵
d
[
s
t
a
r
t
+
1
]
=
a
r
r
[
s
t
a
r
t
+
1
]
−
a
r
r
[
s
t
a
r
t
]
a
r
r
[
s
t
a
r
t
+
1
]
+
=
x
,
a
r
r
[
s
t
a
r
t
]
+
=
x
∴
d
[
s
t
a
r
t
+
1
]
保持不变
对于
d
[
s
t
a
r
t
+
2...
e
n
d
]
,可以同理得到证明
对arr[start...end]+=x\\ ∵d[start]=arr[start]-arr[start-1]\\ arr[start]+=x,arr[start-1]不变\\ ∴d[start]+=x \\ \\ 又∵d[end+1]=arr[end+1]-arr[end]\\ arr[end]+=x,arr[end+1]不变\\ ∴d[end+1]-=x \\ \\ 而对于d[start+1...end],我们以d[start+1]为例:\\ ∵d[start+1]=arr[start+1]-arr[start]\\ arr[start+1]+=x, arr[start]+=x ∴d[start+1]保持不变\\ 对于d[start+2...end],可以同理得到证明
对arr[start...end]+=x∵d[start]=arr[start]−arr[start−1]arr[start]+=x,arr[start−1]不变∴d[start]+=x又∵d[end+1]=arr[end+1]−arr[end]arr[end]+=x,arr[end+1]不变∴d[end+1]−=x而对于d[start+1...end],我们以d[start+1]为例:∵d[start+1]=arr[start+1]−arr[start]arr[start+1]+=x,arr[start]+=x∴d[start+1]保持不变对于d[start+2...end],可以同理得到证明
因此,当我们需要对一个很大的区间进行统一的加减时,利用差分数组只需要修改两个下标值即可完成该工作。
这里有 n 个航班,它们分别从 1 到 n 进行编号。
有一份航班预订表 bookings,表中第 i 条预订记录 bookings[i] = [firsti, lasti, seatsi] 意味着在从 firsti 到 lasti(包含 firsti 和 lasti )的每个航班上预订了seatsi个座位。
请你返回一个长度为 n 的数组 answer,里面的元素是每个航班预定的座位总数。
输入:bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
输出:[10,55,45,25,25]
解释:
航班编号 1 2 3 4 5
预订记录 1 :10 10
预订记录 2 : 20 20
预订记录 3 : 25 25 25 25
总座位数: 10 55 45 25 25
因此,answer = [10,55,45,25,25]
bookings[i] = [firsti, lasti, seatsi],意味着给航班编号为[firsti, last]统一加上座位数seatsi,这就是差分数组的典型应用:区间快速加减。
由于每个航班初始座位为0,因此原数组arr每个元素为0,即差分数组每个元素为0。
通过遍历bookings数组,对差分数组进行加减,最后通过差分数组还原arr即可!
vector corpFlightBookings(vector>& bookings, int n)
{
vector d(n + 2, 0); // 多开空间,方便编号到数组下标的直接映射
for (auto booking : bookings)
{
// 为区间:[ booking[0], booking[1] ] 增值booking[2]
// 只需要修改差分数组的booking[0]和booking[1]+1
d[booking[0]] += booking[2];
d[booking[1] + 1] -= booking[2];
}
vector res(n); // 结果数组长度必须为n,因此下标i映射航班i+1
for (int i = 0; i < n; ++i)
{
if (i == 0)
{
res[i] = d[i + 1];
}
else
{
res[i] = res[i - 1] + d[i + 1];
}
}
return res;
}