题目
输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1, y1, x2, y2,表示一个子矩阵的左上角坐标和右下角坐标。
对于每个询问输出子矩阵中所有数的和。
输入格式
第一行包含三个整数n,m,q。
接下来n行,每行包含m个整数,表示整数矩阵。
接下来q行,每行包含四个整数x1, y1, x2, y2,表示一组询问。
输出格式
共q行,每行输出一个询问的结果。
数据范围
1≤n,m≤1000,
1≤q≤200000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤矩阵内元素的值≤1000
输入样例:
3 4 3
1 7 2 4
3 6 2 8
2 1 2 3
1 1 2 2
2 1 3 4
1 3 3 4
输出样例:
17
27
21
解题思路
因为同样是求某个区域的和,因此同样使用前缀和会简化求和操作,每次查询只是找指定数组的点,而不必遍历数组.
搭建矩阵的前缀和数组会稍显复杂,但是一样不困难.首先我们知道前缀和数组的每一个数都是由前边的前缀和数组的数得来的,且前缀和数组的值是从小到大慢慢建立起来,也即是说,当我想得到s[i][j]
时,只要合理利用前边的数组,就一定能得到.说到这里似乎跟递归思想很接近?bp问题好像也是这个思路?
那么s[i][j]
究竟怎么求呢?
最简单的方法就是利用他上方周边的数组值,因此
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]
//其中a[i][j]其实可以直接由输入得到
这样前缀和数组就建立完成了,求某矩阵的和就只是加加减减了.
源代码
import java.util.Scanner;
class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int q=sc.nextInt();
int[][] list_sum=new int[1010][1010];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x=sc.nextInt();
list_sum[i][j]=list_sum[i][j-1]+list_sum[i-1][j]-list_sum[i-1][j-1]+x;
}
}
while(q-->0){
int x1=sc.nextInt();
int y1=sc.nextInt();
int x2=sc.nextInt();
int y2=sc.nextInt();
int res=list_sum[x2][y2]-list_sum[x2][y1-1]-list_sum[x1-1][y2]+list_sum[x1-1][y1-1];
System.out.println(res);
}
}
}