差分简介
差分是一种用于高效处理区间增减操作的数据结构或算法技巧,常见于数组操作。其核心思想是通过维护相邻元素的差值,将区间操作转化为单点操作,从而降低时间复杂度。
差分数组的构建
给定原数组 A
,其差分数组 D
定义为:
D[0] = A[0]
(若数组从0开始)。D[i] = A[i] - A[i-1]
(i > 0
)。
示例代码:
vector<int> buildDiffArray(const vector<int>& A) {
int n = A.size();
vector<int> D(n);
D[0] = A[0];
for (int i = 1; i < n; ++i) {
D[i] = A[i] - A[i-1];
}
return D;
}
区间增减操作
对原数组 A
的区间 [l, r]
进行增减操作时,只需修改差分数组 D
的两个端点:
D[l] += val
:表示从l
开始的所有元素增加val
。D[r+1] -= val
(若r+1
在数组范围内):表示从r+1
开始的所有元素取消之前的增加。
示例代码:
void applyDiffOperation(vector<int>& D, int l, int r, int val) {
D[l] += val;
if (r + 1 < D.size()) {
D[r+1] -= val;
}
}
还原原数组
通过差分数组 D
还原原数组 A
时,只需计算前缀和:
A[0] = D[0]
。A[i] = A[i-1] + D[i]
(i > 0
)。
示例代码:
vector<int> restoreArray(const vector<int>& D) {
int n = D.size();
vector<int> A(n);
A[0] = D[0];
for (int i = 1; i < n; ++i) {
A[i] = A[i-1] + D[i];
}
return A;
}
应用场景
- 多次区间修改:如对数组进行大量区间增减操作,差分可将每次操作的时间复杂度从
O(n)
降至O(1)
。 - 离线查询:适用于所有修改完成后才需要查询结果的场景。
示例问题
假设需要对数组 [1, 2, 3, 4, 5]
的区间 [1, 3]
增加 2
:
- 构建差分数组
[1, 1, 1, 1, 1]
。 - 应用操作后差分数组变为
[1, 3, 1, 1, -1]
。 - 还原原数组得到
[1, 4, 5, 6, 5]
。
差分技术广泛应用于算法竞赛和数据处理中,尤其适合需要高效处理动态区间操作的场景。