(^ _ ^)
这个题
差分数组是一种用于高效处理区间更新操作的数据结构。它在处理数组中的区间增减操作时非常有用,能够将区间更新的时间复杂度从 O(n) 降低到 O(1)。
差分数组的定义
给定一个数组 a
,其差分数组 diff
定义为:
diff[0] = a[0]
(第一个元素保持不变);- 对于
i > 0
,diff[i] = a[i] - a[i-1]
(当前元素与前一个元素的差值)。
差分数组的性质:
- 差分数组的前缀和可以还原原始数组。
- 对差分数组进行区间更新操作,可以高效地反映到原始数组中。
差分数组的作用
差分数组的核心作用是高效处理区间更新。例如:
- 如果需要对数组
a
的区间[L, R]
中的每个元素增加一个值val
,可以通过对差分数组diff
进行以下操作:diff[L] += val
;diff[R+1] -= val
(如果R+1
在数组范围内)。
通过这种方式,区间更新的时间复杂度从 O(n) 降低到 O(1)。
差分数组的示例
示例 1:构造差分数组
假设原始数组为:
a = [2, 5, 3, 1, 4]
其差分数组 diff
为:
diff[0] = a[0] = 2
diff[1] = a[1] - a[0] = 5 - 2 = 3
diff[2] = a[2] - a[1] = 3 - 5 = -2
diff[3] = a[3] - a[2] = 1 - 3 = -2
diff[4] = a[4] - a[3] = 4 - 1 = 3
所以差分数组为:
diff = [2, 3, -2, -2, 3]
示例 2:通过差分数组还原原始数组
对差分数组 diff
求前缀和,可以还原原始数组 a
:
a[0] = diff[0] = 2
a[1] = diff[0] + diff[1] = 2 + 3 = 5
a[2] = diff[0] + diff[1] + diff[2] = 2 + 3 + (-2) = 3
a[3] = diff[0] + diff[1] + diff[2] + diff[3] = 2 + 3 + (-2) + (-2) = 1
a[4] = diff[0] + diff[1] + diff[2] + diff[3] + diff[4] = 2 + 3 + (-2) + (-2) + 3 = 4
还原后的原始数组为:
a = [2, 5, 3, 1, 4]
示例 3:区间更新
假设我们需要对原始数组 a
的区间 [1, 3]
中的每个元素增加 2
,可以通过差分数组实现:
- 对差分数组
diff
进行以下操作:diff[1] += 2
;diff[4] -= 2
(因为R+1 = 4
)。
- 更新后的差分数组为:
diff = [2, 5, -2, -2, 1]
- 通过差分数组还原原始数组:
更新后的原始数组为:a[0] = 2 a[1] = 2 + 5 = 7 a[2] = 2 + 5 + (-2) = 5 a[3] = 2 + 5 + (-2) + (-2) = 3 a[4] = 2 + 5 + (-2) + (-2) + 1 = 4
a = [2, 7, 5, 3, 4]
差分数组的应用场景
-
区间增减操作:
- 对数组的某个区间进行统一的增减操作。
- 例如:对数组
a
的区间[L, R]
中的每个元素增加val
。
-
高效计算区间和:
- 结合前缀和,可以高效计算区间和。
-
动态数组更新:
- 在需要频繁更新数组区间值的场景中,差分数组可以显著提高效率。
代码实现
以下是差分数组的 cpp实现:
#include <iostream>
#include <vector>
using namespace std;
vector<int> build_diff_array(const vector<int>& a) {
int n = a.size();
vector<int> diff(n);
diff[0] = a[0];
for (int i = 1; i < n; ++i) {
diff[i] = a[i] - a[i - 1];
}
return diff;
}
void update_diff_array(vector<int>& diff, int L, int R, int val) {
diff[L] += val;
if (R + 1 < diff.size()) {
diff[R + 1] -= val;
}
}
vector<int> restore_array(const vector<int>& diff) {
vector<int> a;
a.push_back(diff[0]);
for (int i = 1; i < diff.size(); ++i) {
a.push_back(a[i - 1] + diff[i]);
}
return a;
}
int main() {
vector<int> a = {2, 5, 3, 1, 4};
vector<int> diff = build_diff_array(a);
cout << "Difference array: ";
for (int num : diff) {
cout << num << " ";
}
cout << endl; // Output: [2, 3, -2, -2, 3]
update_diff_array(diff, 1, 3, 2);
cout << "Updated difference array: ";
for (int num : diff) {
cout << num << " ";
}
cout << endl; // Output: [2, 5, -2, -2, 1]
vector<int> a_updated = restore_array(diff);
cout << "Updated original array: ";
for (int num : a_updated) {
cout << num << " ";
}
cout << endl; // Output: [2, 7, 5, 3, 4]
return 0;
}
总结
差分数组是一种非常实用的工具,特别适合处理区间更新问题。它的核心思想是通过记录相邻元素的差值,将区间更新操作转化为单点更新操作,从而大幅提高效率。
AC代码
#include <iostream>
using namespace std;
const int MAXN = 1005;
int diff[MAXN][MAXN]; // 定义二维差分数组
int main() {
int n, m;
cin >> n >> m;
// 处理每一块地毯
for (int i = 0; i < m; ++i) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
// 在差分数组上进行标记
diff[x1][y1]++;
diff[x2 + 1][y1]--;
diff[x1][y2 + 1]--;
diff[x2 + 1][y2 + 1]++;
}
// 还原原数组
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
// 通过前缀和运算还原
diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1];
cout << diff[i][j];
if (j < n) {
cout << " ";
}
}
cout << endl;
}
return 0;
}