差分

  • 差分就是数组 a 构造一个查分数组 b (一般选择值为0的两个数组),差分数组 b 的相应位置的前缀和代表了数组 a 中每个位置的结果,对于在一个区间里增加或者减小某个数,对于前缀和来说是o1的,所以对于a中某个区间进行同样的操作也是o1,对a矩阵的操作等价于对b矩阵的操作
  • 一维

如果想要在数组a的 l 到 r 区间的每个数增加 c ,我们可以想到的一种办法是线性扫描一遍,复杂度为n级别,是否可以做到复杂度为1呢?

利用差分可以实现,我们需要一个辅助数组b,其实 a 中每个元素均为 b 数组中对应位置的前缀和,采用b【l】 += c,b【r+1】-= c 可以实现数组 a 从 l 到 r 每个元素增加 c ,由于只有两条语句,所以时间复杂度是1的,最后我们需要把b数组的前缀和求出可得数组 a ,具体请看下面的代码(c++实现)

 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 const int N = 100000+10;
 7 
 8 //构造了一个a的差分数组b,因为此时a数组中 a[i] = b[1] + b[2] + ... + b[i]; a数组为b数组的前缀和
 9 vector<int> a(N,0);
10 vector<int> b(N,0);
11 
12 int n, m;
13 
14 //从a数组的 l 到 r区间内插入c,也就是在b数组的 l 处插入c 在 r+1 处 - c,因为a数组是b的前缀和
15 void insert(int l, int r, int c){
16     b[l] += c;
17     b[r + 1] -= c;
18 }
19 
20 int main(){
21     cin >> n >> m;
22     for(int i = 1;i <= n;++i) cin >> a[i];
23     
24     for(int i = 1;i <= n;++i) insert(i, i, a[i]);//相当于从i 到 i 区间每个数增加c ,表现在b 数组上
25     
26     for(int i = 0;i < m;++i){
27         int l, r, c;
28         cin >> l >> r >> c;
29         insert(l, r, c);//从 l 到 r 区间插入 c ,表现在b上, 但是实质在a上,因为一会要求b 的 前缀和
30     }
31     
32     for(int i = 1;i <= n;++i) a[i] = a[i - 1] + b[i];//a[i] 为 b[i] 的前缀和 ,就是a[i] 从l 到 r 之间每个数增加c的结果
33     
34     for(int i = 1;i <= n;++i) cout << a[i] << " ";
35     
36     return 0;
37 }
View Code
  •  二维
 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 const int N = 1000+10;
 7 //构造a是b的前缀和矩阵,b是a的差分矩阵
 8 vector<vector<int>> a(N,vector<int>(N,0));
 9 vector<vector<int>> b(N,vector<int>(N,0));
10 
11 int n, m, q;//n 行 m 列
12 // x1,y1 为左上角下标 x2,y2为右下角下标 , 函数功能为在 x1,y1 and x2,y2 构成的矩阵每个元素加 c 
13 void insert(int x1, int y1, int x2, int y2, int c){
14     b[x1][y1] += c;    
15     b[x2 + 1][y1] -= c;
16     b[x1][y2 + 1] -= c;
17     b[x2 + 1][y2 + 1] += c;
18 }
19 
20 int main(){
21     cin >> n >> m >> q;    
22     
23     for(int i = 1;i <= n;++i)
24         for(int j = 1;j <= m;++j)
25             cin >> a[i][j];
26             
27     for(int i = 1;i <= n;++i)
28         for(int j = 1;j <= m;++j)
29             insert(i, j, i, j, a[i][j]);
30             
31     for(int i = 0;i < q;++i){
32         int x1,y1,x2,y2,c;
33         cin >> x1 >> y1 >> x2 >> y2 >> c;
34         insert(x1, y1, x2, y2, c);
35     }
36     
37     for(int i = 1;i <= n;++i){
38         for(int j = 1;j <= m;++j){
39             a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + b[i][j];//计算b的前缀和赋值给a
40             cout << a[i][j] << " ";
41         }
42         cout << endl;
43     }
44     
45    return 0; 
46 }
View Code
原文地址:https://www.cnblogs.com/sxq-study/p/12069735.html