其实并不是很难的东西,只是怕又忘记了所以才写博客。
前缀和 构造数组b
为输入数组a
的前缀和,输出一段数列的和时时间复杂度为O(1),适合大量的输出。
一维前缀和 模板题
显然无什么好说的
在输入时b[i] = b[i - 1] + a[i]
以构造前缀和数组 即可
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <bits/stdc++.h> using namespace std;const int lxb = 1e5 + 10 ;int q[lxb];int n, m;int main () { cin >> n >> m; for (int i = 1 ; i <= n; i ++) { int x; cin >> x; q[i] = q[i - 1 ] + x; } for (int i = 1 ; i <= m; i ++) { int l, r; cin >> l >> r; cout << q[r] - q[l - 1 ] << endl; } return 0 ; }
二维前缀和 模板题
其实本质上差别不大
简单推理便可以得到x1,y1,x2,y2区间查询的和为
s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <bits/stdc++.h> using namespace std;const int lxb = 1010 ;int a[lxb][lxb],s[lxb][lxb];int n, m, q;int main () { cin >> n >> m >> q; for (int i = 1 ; i <= n; i ++) { for (int j = 1 ; j <= m; j ++) { scanf ("%d" ,&a[i][j]); s[i][j] = s[i][j - 1 ] + s[i - 1 ][j] - s[i - 1 ][j - 1 ] + a[i][j]; } } while (q --) { int x1, y1, x2, y2; scanf ("%d%d%d%d" , &x1, &y1, &x2, &y2); int ans = s[x2][y2] - s[x1 -1 ][y2] - s[x2][y1 -1 ] + s[x1 -1 ][y1 -1 ]; cout << ans << endl; } return 0 ; }
差分 差分便是构造的b数组
的前缀和为输入数组a
的前缀和,改变一个区间数据的时间复杂度为O(1),适合频繁插入数据。
自己一般会理解为反向前缀和
一维差分 模板题
无话可说
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> using namespace std;const int N = 100010 ;int n, m;int a[N], b[N];void insert (int l, int r, int c) { b[l] += c; b[r + 1 ] -= c; } int main () { scanf ("%d%d" , &n, &m); for (int i = 1 ; i <= n; i ++ ) scanf ("%d" , &a[i]); for (int i = 1 ; i <= n; i ++ ) insert (i, i, a[i]); while (m -- ) { int l, r, c; scanf ("%d%d%d" , &l, &r, &c); insert (l, r, c); } for (int i = 1 ; i <= n; i ++ ) b[i] += b[i - 1 ]; for (int i = 1 ; i <= n; i ++ ) printf ("%d " , b[i]); return 0 ; }
二维差分 其实也是一样的道理,简单推理便可以得到
若想使x1,y1,x2,y2
区间的数都加上加上一个c
只需要对b数组
做以下操作
b[x1][y1] += c
b[x1][y2 + 1] -= c
b[x2 + 1][y1], -= c
b[x2 + 1][y2 + 1] += c
模板题
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 #include <bits/stdc++.h> using namespace std;const int lxb = 1e3 + 10 ;int n, m, q;int a[lxb][lxb], b[lxb][lxb];void insert (int x1, int y1, int x2, int y2, int c) { b[x1][y1] += c; b[x1][y2 + 1 ] -= c; b[x2 + 1 ][y1] -= c; b[x2 +1 ][y2 + 1 ] += c; } int main () {cin >> n >> m >> q; for (int i = 1 ; i <= n; i ++) for (int j = 1 ; j <= m; j ++) { scanf ("%d" ,&a[i][j]); } for (int i = 1 ; i <= n; i ++) for (int j = 1 ; j <= m; j ++) { insert (i,j,i,j,a[i][j]); } while (q --){ int x1,y1,x2,y2,c; cin >> x1 >> y1 >> x2 >> y2 >> c; insert (x1,y1,x2,y2,c); } for (int i = 1 ; i <= n; i ++){ for (int j = 1 ; j <= m; j ++) { b[i][j] += b[i - 1 ][j] + b[i][j - 1 ] - b[i -1 ][j - 1 ]; } } for (int i = 1 ; i <= n; i ++) { for (int j = 1 ; j <= m; j ++) { printf ("%d " ,b[i][j]); } puts (" " ); } return 0 ; }