#5433. 一维差分数组笔记
一维差分数组笔记
📊 差分数组算法笔记
🎯 问题背景
在处理数组的区间修改问题时,如果直接使用暴力方法,可能会因为时间复杂度太高而导致超时⏰。差分数组是一种高效处理区间修改问题的数据结构,就像变魔术一样神奇!✨
💥 暴力方法的问题
🐌 暴力方法实现
#include<bits/stdc++.h>
using namespace std;
int a[1000010];
int main(){
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
int x, y, z;
while(k--){
cin >> x >> y >> z;
// 🚫 暴力方法:对区间内每个元素逐个修改
// 这就像一个人一个人地发糖果,太慢了!
for(int i = x; i <= y; i++){
a[i] += z;
}
}
for(int i = 1; i <= n; i++){
cout << a[i] << " ";
}
return 0;
}
📈 暴力方法的时间复杂度分析
| 操作类型 | 时间复杂度 | 比喻说明 |
|---|---|---|
| 单次区间修改 | O(y-x+1) | 🐢 像蜗牛一样慢 |
| k次修改 | O(k×n) | ⏳ 等待时间太长 |
| 总体复杂度 | O(n + k×n) | 💀 会导致超时 |
数据样例演示:
n = 1000000, k = 1000000
暴力方法:1000000 × 1000000 = 1,000,000,000,000 次操作 ❌
差分数组:1000000 + 1000000 = 2,000,000 次操作 ✅
当n和k都很大时,暴力方法就像让一个人数完整个沙滩的沙子🏖️,而差分数组就像用机器快速扫描!
🚀 差分数组优化
💡 差分数组核心思想
差分数组b[i]定义为:b[i] = a[i] - a[i-1]
通过维护差分数组,可以将区间修改操作转化为两个单点修改操作,就像用杠杆撬动地球一样省力!🎯
🛠️ 差分数组实现
#include<bits/stdc++.h>
using namespace std;
int a[1000010], b[1000010];
int main(){
// 输入n个数字,对n个数字进行k次修改
// 每次修改是对区间[x,y]之间的数字增加z
int n, k;
cin >> n >> k;
// 输入原始数组并构建差分数组
for(int i = 1; i <= n; i++){
cin >> a[i];
b[i] = a[i] - a[i-1]; // 🏗️ 构建差分数组
}
int x, y, z;
while(k--){
cin >> x >> y >> z;
// 🎯 差分数组的核心操作 - 就像开关控制一样精准!
b[x] += z; // ✅ 区间开始处打开"增加阀门"
b[y+1] -= z; // ✅ 区间结束后关闭"增加阀门"
}
// 通过差分数组还原最终数组
for(int i = 1; i <= n; i++){
a[i] = a[i-1] + b[i]; // 🔄 前缀和还原
}
// 输出结果
for(int i = 1; i <= n; i++){
cout << a[i] << " ";
}
return 0;
}
🎨 差分数组原理详解
1. 📐 差分数组定义
原始数组: a = [a₁, a₂, a₃, ..., aₙ]
差分数组: b = [b₁, b₂, b₃, ..., bₙ]
其中: bᵢ = aᵢ - aᵢ₋₁
2. 🎪 区间修改原理演示
例子: 数组 [1, 2, 3, 4, 5],对区间 [2, 4] 增加 3
原始数组: [1, 2, 3, 4, 5]
差分数组: [1, 1, 1, 1, 1]
修改操作: b[2] += 3, b[5] -= 3
修改后差分: [1, 4, 1, 1, -2]
还原数组:
a₁ = 1
a₂ = 1 + 4 = 5
a₃ = 5 + 1 = 6
a₄ = 6 + 1 = 7
a₅ = 7 - 2 = 5
最终结果: [1, 5, 6, 7, 5] 🎉
3. 🔄 前缀和还原过程可视化
差分数组: [b₁, b₂, b₃, b₄, b₅]
↓ ↓ ↓ ↓ ↓
原始数组: [b₁, b₁+b₂, b₁+b₂+b₃, b₁+b₂+b₃+b₄, b₁+b₂+b₃+b₄+b₅]
⏱️ 时间复杂度对比
| 方法 | 构建 | 单次修改 | k次修改 | 还原 | 总计 | 性能评价 |
|---|---|---|---|---|---|---|
| 暴力 | O(n) | O(n) | O(k×n) | O(n) | O(k×n) | 🐢 太慢了! |
| 差分 | O(1) | O(k) | O(n+k) | 🚀 飞一般的速度! |
性能提升对比:
当 n=10⁶, k=10⁶ 时:
暴力方法:10¹² 次操作 ≈ 16分钟 ⏰
差分数组:2×10⁶ 次操作 ≈ 0.003秒 ⚡
速度提升:500,000倍! 🤯
🎯 应用场景
差分数组特别适用于以下场景:📋
- 🎮 多次区间加减操作 - 就像游戏中的区域效果
- 📊 区间修改后需要查询最终结果 - 批量处理数据
- 🏆 时间限制严格的编程竞赛题目 - ACM/ICPC等比赛必备技能
⚠️ 注意事项
- 🎯 数组下标从1开始,避免边界问题
- 🚧 注意
b[y+1]可能越界,需要保证数组大小足够 - 📦 差分数组主要用于离线处理,不适合需要频繁查询中间结果的场景
🎓 学习建议
- 🧩 先理解概念:把差分数组想象成"变化量的记录本" 📒
- 🔢 手动模拟:用纸笔计算小例子,加深理解 ✏️
- 💻 多写代码:实现几个变种题目,熟能生巧 🏋️
- 🎯 识别模式:遇到"区间修改"关键词,立即想到差分数组 💡
通过使用差分数组,我们可以将区间修改问题的时间复杂度从O(n)优化到O(1),在处理大规模数据时避免超时问题。就像从步行🚶升级到乘坐火箭🚀一样的效果!
记住:聪明的算法选择 > 盲目的暴力求解 🧠 > 💪
Happy Coding! 🎉👨💻👩💻