Niuke.com DP35 [Template] Two-dimensional prefix sum

Code:
 

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextInt()) { // 注意 while 处理多个 case
           int n=in.nextInt();
           int m=in.nextInt();
           int q=in.nextInt();

           //因为题目中的矩阵下标从 1 开始,而我们创建的数组下标从 0 开始,所以需要留一行
           int[][]arr=new int[n+1][m+1];
           for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                arr[i][j]=in.nextInt();
            }
           }

           //获取前缀和数组 dp
           //记录的是区间数据的总和,很容易溢出,所以用 long 类型
           long[][]dp=new long[n+1][m+1];
           //填充 dp 数组
           for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1]+arr[i][j];
            }

           }

           //循环查询 q 次
           while(q>0){
            int x1=in.nextInt();
            int y1=in.nextInt();
            int x2=in.nextInt();
            int y2=in.nextInt();

            //使用 dp 数组
            System.out.println(dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]);
            q--;
           }
        }
    }
}

answer:

        The question requires us to obtain the sum of data in the interval (x1, y1) ~ (x2, y2). This is a typical prefix sum problem. If we use a brute force solution, we need to traverse all the data in this interval in the array and query We need to traverse q times q times, so the time complexity will be O(n*m*q). Using brute force to solve this problem will definitely take too long.

        So we need to use the prefix and solution method. We can define a prefix sum array dp. dp[i][j] represents the sum of data in the interval from (1, 1) to (i, j), because we want to count the (1,1) to the sum of data in each position interval, so the size of the dp array is the same as the size of the two-dimensional array arr

        Now we first consider how to fill the dp array, and then consider how to use the dp array to obtain the results. Generally, the data in row 0 and column 0 of the dp array are initialized manually. , rather than filled by the program, in order to avoid out-of-bounds problems (explained later), so for example 1, the dp array we have not filled yet is as follows

        0        1        2        3        4        5

0      0        0        0        0        0        0

1      0

2      0

3      0

        Because the array subscript given in the question starts from 1, the position with the subscript 0 does not exist, so the prefix sum is set to 0, which also means that we have already filled in dp[i][j] Knowing the values ​​of dp[ i-1 ][ j-1 ], dp[ i ][ j-1 ], dp[ i-1 ][ j ], how do we calculate the value of dp[ i ][ j ]? In order to facilitate understanding, I drew the following picture:

        We want to calculate dp[i][j], that is, the sum of data in the interval from (1, 1) to (i, j). According to the picture on the right, what we want to calculate is A+B+C+D Area, we can replace this formula with (A+C)+(A+B)-A+D. The area of ​​A+C is the value of dp[i][j-1], and the area of ​​A+B is The value of dp[ i-1 ][ j ], the area of ​​A is the value of dp[ i-1 ][ j-1 ], and the area of ​​D is the value of arr[ i ][ j ]

        So we can get the formuladp[ i ][ j ] = dp[ i ][ j-1 ] + dp[ i-1 ][ j ] - dp [ i-1 ][ j-1 ] + arr[ i ][ j ], the order of filling the dp array is from left to right and then from top to bottom,< a i=3>According to this formula, when i=0 or j=0, there will be a subscript of -1, and there is an out-of-bounds problem

        Now that we have the filling formula of the dp array, we will study how to get the result through the dp array to solve the problem. In order to facilitate understanding, I drew the following picture

        As shown above, we want to get the sum of data x in the interval (x1, y1) ~ (x2, y2), which is equivalent to calculating 

The value of s - A - B - C, we modify the expression to s - (A+B) - (A+C) + A, the surface of s is dp[x2][y2], the area of ​​A+B It is dp[ The sum of data in the interval y1) ~ (x2, y2) x = dp[ x2 ][ y2 ] - dp[ x2 ][ y1-1 ] - dp[ x1-1 ][ y2 ] + dp[ x1-1 ] [y1-1] 

        The two expressions above are the core of this question

Guess you like

Origin blog.csdn.net/q322359/article/details/135036182