模版
注意,对区间更新用的是差分数组,而求任何一个区间的和用的是前缀和数组。
-
原数组转差分数组
diff[i][j] = diff[i][j] - diff[i - 1][j] + diff[i][j - 1] + diff[i - 1][j - 1]
-
把差分数组还原为原数组
diff[i][j] += diff[i - 1][j] + diff[i][j - 1] - diff[i - 1][j - 1]
-
用前缀和数组求
到
的所有元素和
ans = sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 -1][y1 - 1]
-
用差分数组将
到
的所有元素加target
public static void add(int x1, int y1, int x2, int y2, int target) {
diff[x1][y1] += target;
diff[x1][y2 + 1] -= target;
diff[x2 + 1][y1] -= target;
diff[x2 + 1][y2 + 1] += target;
}
P3397
这道题要对二维区间进行维护,于是使用差分数组,最后再复原为原数组。
import java.io.*;
public class P3397 {
public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer t = new StreamTokenizer(br);
public static PrintWriter out = new PrintWriter(bw);
public static int nextInt() throws Exception {
t.nextToken();
return (int) t.nval;
}
public static int n, m;
public static int[][] carpet;
public static void add(int x1, int y1, int x2, int y2, int target) {
carpet[x1][y1] += target;
carpet[x1][y2 + 1] -= target;
carpet[x2 + 1][y1] -= target;
carpet[x2 + 1][y2 + 1] += target;
}
public static void back() {
for (int i = 1; i <= n; i += 1) {
for (int j = 1; j <= n; j += 1) {
carpet[i][j] += carpet[i - 1][j] + carpet[i][j - 1] - carpet[i - 1][j - 1];
out.print(carpet[i][j] + " ");
}
out.println();
out.flush();
}
}
public static void main(String[] args) throws Exception {
n = nextInt();
m = nextInt();
carpet = new int[n + 2][n + 2];
for (int i = 1; i <= m; i += 1) {
add(nextInt(), nextInt(), nextInt(), nextInt(), 1);
}
back();
}
}
P1719
构造二位前缀和, 计算任何一个矩阵的和。
import java.util.Scanner;
public class P1719 {
public static int n, max;
public static int[][] matrix;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
matrix = new int[n + 1][n + 1];
for (int i = 1; i <= n; i += 1) {
for (int j = 1; j <= n; j += 1) {
matrix[i][j] = matrix[i - 1][j] + matrix[i][j - 1] - matrix[i - 1][j - 1] + in.nextInt();
}
}
for (int x1 = 1; x1 <= n; x1 += 1) {
for (int y1 = 1; y1 <= n; y1 += 1) {
for (int x2 = x1; x2 <= n; x2 += 1) {
for (int y2 = y1; y2 <= n; y2 += 1) {
int sum = matrix[x2][y2] - matrix[x2][y1 - 1] - matrix[x1 - 1][y2] + matrix[x1 - 1][y1 - 1];
max = Math.max(max, sum);
}
}
}
}
System.out.print(max);
}
}
P1387
正方形也就是一个矩阵内的和等于边长的平方,要求任何一个区间的和,用前缀和数组。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
public class P1387 {
public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static StreamTokenizer t = new StreamTokenizer(br);
public static int nextInt() throws Exception {
t.nextToken();
return (int) t.nval;
}
public static int n, m;
public static void main(String[] args) throws Exception{
n = nextInt(); m = nextInt();
int ans = 0;
int[][] grid = new int[n + 1][m + 1];
Arrays.fill(grid[0], 0);
for (int i = 1; i <= n; i += 1) {
grid[i][0] = 0;
}
for (int i = 1; i <= n; i += 1) {
for (int j = 1; j <= m; j += 1) {
grid[i][j] += grid[i - 1][j] + grid[i][j - 1] - grid[i - 1][j - 1] + nextInt();
}
}
for(int i = 1; i <= n; i += 1) {
for (int j = 1; j <= m; j += 1) {
for (int a = 1; a <= Math.min(n - i + 1, m - j + 1); a += 1 ) {
int x = i + a - 1, y = j + a - 1;
if (grid[x][y] - grid[x][j - 1] - grid[i - 1][y] + grid[i - 1][j - 1] == a * a) {
ans = Math.max(ans, a);
}
}
}
}
System.out.print(ans);
}
}