给你一个 n 行 m 列的矩阵 A ,下标从1开始。
接下来有 q 次查询,每次查询输入 4 个参数 x1 , y1 , x2 , y2
请输出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和,
输入描述:
第一行包含三个整数n,m,q.
接下来n行,每行m个整数,代表矩阵的元素
接下来q行,每行4个整数x1, y1, x2, y2,分别代表这次查询的参数
数据范围
输出描述:
输出q行,每行表示查询结果。
示例1
输入:
3 4 3 1 2 3 4 3 2 1 0 1 5 7 8 1 1 2 2 1 1 3 3 1 2 3 4
复制输出:
8 25 32
复制
备注:
读入数据可能很大,请注 意读写时间。
这是一个二维前缀和的问题,可以先预处理出一个前缀和矩阵,然后每次查询时直接用前缀和矩阵计算即可。
定义dp[i][j]来储存在(i,j)前及(i,j)的所有数据之和。
思考一下,得出dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]的状态状态方程。
假设是这两个点位,那么后面这张图多划的则是需要减去的。
两个矩形相交的地方多减掉了一次,所以需要加上dp[x1-1][y1-1]
最终的ans=ans=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1];
以下是完全代码
#include <stdio.h>
long long int dp[1001][1001]={0},c[1001][1001]={0};
int main() {
long long int a, b,i,j,n,m,x,q,x1,x2,y1,y2,ans=0,k;
scanf("%lld %lld %lld",&n,&m,&q);
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%lld",&c[i][j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
dp[i][j]=dp[i][j-1]+c[i][j]+dp[i-1][j]-dp[i-1][j-1];//dp[i][j]是当前元素到(1,1)所覆盖的数据的总和。
}
}
for(x=1;x<=q;x++){
scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
ans=dp[x2][y2]-dp[x2][y1-1]-dp[x1-1][y2]+dp[x1-1][y1-1];
printf("%lld\n",ans);
}
}
这样,我们就能轻松求出以 (x1, y1) 为左上角 , (x2,y2) 为右下角的子矩阵的和了。