数组方法
#include<iostream>
using namespace std;
long long a[10005][1005], prefixSum[10005][1005]; // 注意调整prefixSum的大小以匹配n
int main() {
int n, m, q;
cin >> n >> m >> q;
// 初始化前缀和数组(第一行和第一列通常为0,除非有特殊需求)
for (int i = 0; i <= n; i++) {
prefixSum[i][0] = 0;
}
for (int j = 0; j <= m; j++) {
prefixSum[0][j] = 0;
}
// 读取矩阵并计算前缀和
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
// 前缀和的正确计算方式
prefixSum[i][j] = a[i][j] + prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1];
}
}
// 处理查询
for (int k = 0; k < q; k++) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
// 注意边界,x1和y1要减1(因为数组是从1开始的,但前缀和数组是从0开始的)
long long sum = prefixSum[x2][y2] - prefixSum[x1-1][y2] - prefixSum[x2][y1-1] + prefixSum[x1-1][y1-1];
cout << sum << '\n';
}
return 0;
}
向量方法
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n, m, q;
cin >> n >> m >> q;
vector<vector<long long>> a(n + 1, vector<long long>(m + 1, 0));
vector<vector<long long>> prefixSum(n + 1, vector<long long>(m + 1, 0));
// 读取矩阵并计算前缀和
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> a[i][j];
prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1] - prefixSum[i-1][j-1] + a[i][j];
}
}
// 处理查询
for (int k = 0; k < q; k++) {
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
// 使用前缀和计算矩形内的和
long long sum = prefixSum[x2][y2] - prefixSum[x1-1][y2] - prefixSum[x2][y1-1] + prefixSum[x1-1][y1-1];
cout << sum << '\n';
}
return 0;
}
说明:
- 前缀和矩阵:
prefixSum[i][j]
存储了从(1,1)
到(i,j)
的矩形区域内所有元素的和。 - 读取和计算前缀和:在读取每个元素
a[i][j]
时,同时更新prefixSum[i][j]
。 - 查询处理:通过四个前缀和值的组合来计算任意矩形
(x1, y1)
到(x2, y2)
内的元素和。
这种方法极大地减少了查询的时间复杂度,使得处理大量查询时更加高效。
超时代码
#include<iostream>
using namespace std;
long long a[10005][1005];
int main()
{
int n,m,x1,x2,y1,y2,q;
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cin>>a[i][j];
}
for(int k=1;k<=q;k++)
{
cin>>x1>>y1>>x2>>y2;
long long sum=0;
for(int i=x1;i<=x2;i++)
{
for(int j=y1;j<=y2;j++)
sum+=a[i][j];
}
cout<<sum<<'\n';
}
return 0;
}