定義
s[n] = \(\sum_{i=1}^na[i]\)c++
遞推關係
s[i] = a[i] + s[i - 1]算法
區間求和
\(\sum_{i=l}^ra[i] = s[r] - s[l - 1]\)數組
定義
存在兩個數組a(a1, a2, a3,..., an)和b(b1, b2, ... ,bn)
若是ai = b1 + b2 + ... + bi
那麼b稱爲a的差分(好比: b1 = a1, b2 = a2 - a1)spa
做用code
構造
差分的構造能夠選擇: b[i] = a[i] - a[i - 1]ci
變形
差分能夠維護a的變化值,即b[i] = Δai = $ \sum_{i=1}^nb[i] $it
#include <bits/stdc++.h> using namespace std; int const N = 1e5 + 10; int s[N], a[N]; int main() { int n, k; cin >> n >> k; // 計算前綴和 for (int i = 1; i <= n ; ++i) { scanf("%d", &a[i]); s[i] = s[i - 1] + a[i]; } // 使用前綴和 for (int i = 0; i < k ; ++i) { int l, r; scanf("%d %d", &l, &r); printf("%d\n", s[r] - s[l -1]); } return 0; }
#include <bits/stdc++.h> using namespace std; int const N = 1e3 + 10; int s[N][N], a[N][N]; int main() { int n, m, k; cin >> n >> m >> k; for (int i = 1; i <= n; ++i) for (int j = 1; j <= m; ++j) { scanf("%d", &a[i][j]); s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j]; // 前綴和在二維的狀況 } for (int i = 0; i < k; ++i) { int l1, r1, l2, r2; scanf("%d %d %d %d", &l1 ,&r1, &l2, &r2); printf("%d\n", s[l2][r2] - s[l2][r1 - 1] - s[l1 - 1][r2] + s[l1 - 1][r1 - 1]); // 打印結果 } return 0; }
#include <bits/stdc++.h> using namespace std; int const N = 1e5 + 10; int b[N], n, m, a[N]; // 區間修改 void insert(int l, int r, int c) { b[l] += c, b[r + 1] -= c; } int main() { cin >> n >> m; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); // 讀入原數組 for (int i = 1, l, r, c; i <= m; ++i) { // 不斷讀入區間增長 scanf("%d %d %d", &l, &r, &c); insert(l, r, c); } for (int i = 1; i <= n; ++i) { b[i] += b[i - 1]; // 計算a[i]的變化值 printf("%d ", a[i] + b[i]); } return 0; }
#include <bits/stdc++.h> using namespace std; int const N = 1e3 + 10; int a[N][N], b[N][N]; int n, m, q; // 區間增長(二維狀況)--和前綴和狀況不同 void insert(int l1, int r1, int l2, int r2, int c) { b[l1][r1] += c; b[l2 + 1][r2 + 1] += c; b[l2 + 1][r1] -= c; b[l1][r2 + 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, l1, r1, l2, r2, c; i <= q; ++i) { scanf("%d%d%d%d%d", &l1, &r1, &l2, &r2, &c); // 區間增長 insert(l1, r1, l2, r2, 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]; // 前綴求和,計算變化量 printf("%d ", a[i][j] + b[i][j]); // 計算變化後的a[i][j] } printf("\n"); } return 0; }