@ZZHow(ZZHow1024)
差分是前缀和的逆运算。
前缀和
前缀和作用:快速求出 [l, r] 区间的和。
一维前缀和
- 例题:AcWing 795. 前缀和
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int[] a = new int[n + 1];int[] s = new int[n + 1];for (int i = 1; i <= n; i++)a[i] = scanner.nextInt(); // 原数组for (int i = 1; i <= n; i++)s[i] = s[i - 1] + a[i]; // 差分数组while (m-- != 0) {int l = scanner.nextInt();int r = scanner.nextInt();System.out.println(s[r] - s[l - 1]); // 求 [l, r] 的和}}
}
二维前缀和
- 例题:AcWing 796. 子矩阵的和
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int q = scanner.nextInt();int[][] a = new int[n + 10][m + 10];int[][] s = new int[n + 10][m + 10];for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)a[i][j] = scanner.nextInt(); // 原矩阵for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j]; // 前缀和矩阵while (q-- != 0) {int x1 = scanner.nextInt();int y1 = scanner.nextInt();int x2 = scanner.nextInt();int y2 = scanner.nextInt();System.out.println(s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]); // 求子矩阵的和}}
}
差分
快速的把 [l, r] 区间中的所有数都加上 C。
一维差分
- 例题:AcWing 797. 差分
import java.util.Scanner;public class Main{public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int[] a = new int[n + 10];int[] b = new int[n + 10];for (int i = 1; i <= n; i++)a[i] = scanner.nextInt(); // 原数组for (int i = 1; i <= n; i++)insert(b, i, i, a[i]); // 差分数组while (m-- != 0) {int l = scanner.nextInt();int r = scanner.nextInt();int c = scanner.nextInt();insert(b, l, r, c); // [l, r] 都加上 c}for (int i = 1; i <= n; i++)b[i] += b[i - 1];for (int i = 1; i <= n; i++)System.out.print(b[i] + " ");}public static void insert(int[] b, int l, int r, int c) {b[l] += c;b[r + 1] -= c;}
}
二维差分
- 例题:AcWing 798. 差分矩阵
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int m = scanner.nextInt();int q = scanner.nextInt();int[][] a = new int[n + 10][m + 10];int[][] b = new int[n + 10][m + 10];for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)a[i][j] = scanner.nextInt(); // 原矩阵for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)insert(b, i, j, i, j, a[i][j]); // 差分矩阵while (q-- != 0) {int x1 = scanner.nextInt();int y1 = scanner.nextInt();int x2 = scanner.nextInt();int y2 = scanner.nextInt();int c = scanner.nextInt();insert(b, x1, y1, x2, y2, c); // 在 (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++)System.out.print(b[i][j] + " ");System.out.println();}}public static void insert(int[][] b, int x1, int y1, int x2, int y2, int c) {b[x1][y1] += c;b[x2 + 1][y1] -= c;b[x1][y2 + 1] -= c;b[x2 + 1][y2 + 1] += c;}
}