题目链接:https://nanti.jisuanke.com/t/T1320
题目描述
给出一个 nn 行 mm 列的矩阵,矩阵的每个位置有一个非负整数 a[i][j]a[i][j],有 qq 次询问,每次询问求一个左上角为 (a,b)(a,b),右下角为 (c,d)(c,d) 的子矩阵的所有数之和。
输入格式
第一行两个整数 n,m,表示矩阵的行和列的大小。
接下来 n 行每行 m 个整数,为矩阵内容。
接下来一行为一个整数 q ,表示询问次数。
接下来 q 行每行 4 个整数 a,b,c,d,含义见题面。
输出格式
共 q 行,第 i 行为第 ii个询问的答案。
数据范围
n×m≤100,000,a[i][j] \le 1000a[i][j]≤1000,q \le 100,000q≤100,000,1 \le a \le c \le n1≤a≤c≤n,1 \le b \le d \le m1≤b≤d≤m。
输出时每行末尾的多余空格,不影响答案正确性
输出时每行末尾的多余空格,不影响答案正确性
样例输入
3 5 1 2 3 4 5 3 2 1 4 7 2 4 2 1 2 3 1 1 3 5 2 2 3 3 1 1 3 3
样例输出
43 9 20
题目分析:
1.这题很容易理解,就是求一个矩阵所有元素的和,但是如果用二维数组求解的话会出问题,因为n×m≤100,000,可能是1*100000,也可能是100000*1,如果定义一个100000*100000的数组又不现实(开不到这么大的数组),所以可以把二维数组存到一位数组里面。当然用vector的话,二维数组也可以采用。
2.下面先看一下用二维数组怎么实现这一题(一维数组和二维数组类似,但是没有二维数组好理解,先用二维数组讲解)
3.最后带上vector的代码
二维代码思路:
如图所示,假设要求S的话,可以用最大的矩形和减去S1+S2,再减去S1+S3,最后再加上S1即可。
二维数组代码:
#include<iostream>
#include<vector>
using namespace std;
int n,m;
int s[1000][1000],dp[1000][1000];
int main()
{
int i,j,q,a,b,c,d;
cin>>n>>m;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>s[i][j];
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+s[i][j];
cin>>q;
while(q--)
{
cin>>a>>b>>c>>d;
cout<<dp[c][d]+dp[a-1][b-1]-dp[a-1][c]-dp[c][b-1]<<endl;
}
return 0;
}
一维数组代码:
#include<iostream>
using namespace std;
int s[200001];
int main()
{
int n,m,i,j,t,q,a,b,c,d;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&t);
s[i*m+j]=s[(i-1)*m+j]+s[i*m+j-1]-s[(i-1)*m+j-1]+t;
}
}
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
printf("%d\n",s[c*m+d]+s[(a-1)*m+b-1]-s[(a-1)*m+d]-s[c*m+b-1]);
}
return 0;
}
一维数组思路:
一维数组和二维数组类似,具体可以看代码。
需要注意的地方:
输入输出要用 scanf 和 printf ,不然会超时。
vector二维数组代码:
#include<iostream>
#include<vector>
using namespace std;
int n,m;
vector<vector<int> > s,dp;
vector<int> k1,k2;
int main()
{
int i,j,q,a,b,c,d,t;
cin>>n>>m;
for(i=0;i<m;i++)
{
k1.push_back(0);
}
s.push_back(k1);
dp.push_back(k1);
for(i=1;i<=n;i++)
{
k1.clear();
k2.clear();
k1.push_back(0);//这是为了把输入的数从下标1开始,这样方便计算
k2.push_back(0);
for(j=1;j<=m;j++)
{
cin>>t;
k1.push_back(t);
k2.push_back(0);
}
s.push_back(k1);
dp.push_back(k2);
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+s[i][j];
cin>>q;
while(q--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
printf("%d\n",dp[c][d]+dp[a-1][b-1]-dp[a-1][d]-dp[c][b-1]);
}
return 0;
}