使用情景
适用于区间频繁修改,而且这个区间范围是比较大的,离线查询的情况。
差分数组的使用
差分数组是前缀和的逆运算, 记原数组为
a
[
N
]
a[N]
a[N], 差分数组
d
i
f
f
[
i
]
=
a
[
i
]
−
a
[
i
−
1
]
diff[i]=a[i]-a[i-1]
diff[i]=a[i]−a[i−1]
如上图所示,如果我们想要将区间(1~6)的所有元素都加1,如果每个元素都+1, 每次操作的复杂度是
O
(
n
)
O(n)
O(n), 总的时间复杂度是
O
(
n
2
)
O(n^2)
O(n2)。
如果引入差分数组 d i f f [ N ] diff[N] diff[N] ,修改段区间[i,j]的元素(都加1),我们只要使得 d i f f [ i ] + 1 , d i f f [ j + 1 ] − 1 diff[i]+1,diff[j+1]-1 diff[i]+1,diff[j+1]−1即可。
之后再对差分数组做前缀和运算即可得到原数组。
例题
2023 4.19 华为机试第一题 服务器耗能统计
oj自测
AC代码
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int n;
int a[1000005];
int main(){
cin>>n;
int max1 = 0, min1 =1e6+10;
while(n--){
int x,y;
cin>>x>>y;
x++,y++;
max1 = max(max1,y);
min1 = min(min1, x);
a[x]++;
a[y+1]--;
}
ll res = 0;
for(int i = min1 ;i<=max1; i++){
a[i] += a[i-1];
if (a[i] == 0 ) res++;
else if (a[i] == 1) res += 3;
else res += 4;
}
cout << res;
}
leecode 1109. 航班预订统计
AC代码
class Solution {
public:
vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
vector<int> ans(n);
for(auto book: bookings){
ans[book[0]-1] += book[2];
if(book[1] < n) ans[book[1]] -= book[2];//注意这里坐标有变化,有点绕
}
for(int i=1; i<n; i++){
ans[i] += ans[i-1];
}
return ans;
}
};
参考文章
- https://oi-wiki.org/basic/prefix-sum/