C++差分风暴:区间修改终极模板

发布于:2025-03-21 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

🔥 差分核心价值

🌟 一维差分模板

1. 核心思想

2. 代码实现

3. 动态图示

📦 二维差分模板

1. 核心公式

2. 代码实现

3. 二维修改示意图

🚨 六大避坑指南

💡 复杂度对比

🌈 LeetCode实战


🔥 差分核心价值

暴力法的痛点

// 区间[l,r]增加val,时间复杂度O(n)  
for(int i=l; i<=r; i++) arr[i] += val; 

差分优势:将区间修改复杂度从 O(n) 降为 O(1),批量操作性能飙升!


🌟 一维差分模板

1. 核心思想
  • 差分数组diff[i] = arr[i] - arr[i-1]

  • 区间修改diff[l] += valdiff[r+1] -= val

  • 还原数组:前缀和计算

2. 代码实现
vector<int> arr = {3,1,4,2,5};  
int n = arr.size();  

// 构建差分数组  
vector<int> diff(n+2, 0); // 多开空间防越界  
for(int i=1; i<=n; i++){  
    diff[i] = arr[i-1] - (i==1 ? 0 : arr[i-2]);  
}  

// 区间[2,4](索引1~3)加10  
int l=2, r=4, val=10;  
diff[l] += val;  
diff[r+1] -= val;  

// 还原数组  
vector<int> new_arr(n);  
new_arr[0] = diff[1];  
for(int i=1; i<n; i++){  
    new_arr[i] = new_arr[i-1] + diff[i+1];  
}  
// 结果:3,11,14,12,5  
3. 动态图示
原数组:  3   1   4   2   5  
差分数组:3  -2   3  -2   3  

操作:区间[2-4]加10  
差分变化:  
diff[2] +=10 → -2+10=8  
diff[5] -=10 → 3-10=-7  

新差分数组:3  8   3  -2  -7  
还原后数组:  
3 → 3+8=11 → 11+3=14 → 14-2=12 → 12-7=5  

📦 二维差分模板

1. 核心公式
给子矩阵(x1,y1)-(x2,y2)加val:  
diff[x1][y1] += val  
diff[x1][y2+1] -= val  
diff[x2+1][y1] -= val  
diff[x2+1][y2+1] += val  
2. 代码实现
vector<vector<int>> matrix = {{1,2,3}, {4,5,6}, {7,8,9}};  
int m = matrix.size(), n = matrix[0].size();  

// 初始化二维差分  
vector<vector<int>> diff(m+2, vector<int>(n+2, 0));  
for(int i=1; i<=m; i++){  
    for(int j=1; j<=n; j++){  
        diff[i][j] += matrix[i-1][j-1];  
        diff[i][j+1] -= matrix[i-1][j-1];  
    }  
}  

// 子矩阵(1,1)-(2,2)加5(原矩阵行0-1,列0-1)  
int x1=1, y1=1, x2=2, y2=2, val=5;  
diff[x1][y1] += val;  
diff[x1][y2+1] -= val;  
diff[x2+1][y1] -= val;  
diff[x2+1][y2+1] += val;  

// 还原矩阵  
vector<vector<int>> res(m, vector<int>(n));  
for(int i=0; i<m; i++){  
    int row_sum = 0;  
    for(int j=0; j<n; j++){  
        row_sum += diff[i+1][j+1];  
        res[i][j] = row_sum;  
    }  
}  
// 结果:  
// 6  7  3  
// 9 10 6  
// 7  8 9  
3. 二维修改示意图
原矩阵:  
1 2 3  
4 5 6  
7 8 9  

差分影响范围:  
+5          -5  
  ↓           ↓  
(1,1)     (1,3)  
  5  -5  
  -5  5  

最终矩阵:  
(1+5)=6  (2+5)=7 3  
(4+5)=9 (5+5+5)=15 6  
7        8       9  

🚨 六大避坑指南

  1. 索引偏移陷阱:原数组从0开始,差分数组从1开始

  2. 越界防护:差分数组多开两格空间

  3. 还原顺序:二维需先计算行前缀和,再列方向累积

  4. 负数处理:差分数组允许负数存在

  5. 多操作叠加:支持连续多次修改后统一还原

  6. 初始值处理:原数组全0时差分数组也全0


💡 复杂度对比

操作 暴力法 差分法
区间修改 O(n) O(1)
单次查询 O(1) O(n)
初始化 O(1) O(n)
适合场景 查多改少 改多查少

🌈 LeetCode实战

  1. 1109. 航班预订统计(一维差分模板题)

  2. 1094. 拼车(差分+上下车模型)

  3. 798. 得分最高的最小轮调(差分+区间覆盖)

  4. 2132. 用邮票贴满网格(二维差分经典)