算法题(129):二维前缀和
审题:
本题需要我们将q组矩阵的和打印出来
思路:
方法一:二维前缀和由于本题使用暴力的模拟方法运行次数高达1e11,会超时,所以我们采用运行次数在1e6的二维前缀和来解题
第一步:前缀和的求法
x = i,y = j的二维矩阵前缀和f[i][j]就是A + B + C + a[i][j]
而为了将式子转化为表达式,我们可以将式子和前缀和联系起来:
(A+B) + (A+C)- A + a[i][j]而A+B的面积就是x=i-1,y=j的位置的前缀和:f[i-1][j]
其他同理,于是转化为:f[i][j] = f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j]
第二步:根据矩阵的左上角坐标和右下角坐标确定矩阵和
思考方法和前面类似:
f[x2][y2] = A+B+C+answer
=> (A+B)+(A+C)-A+answer
最终推导得到:answer = f[x2][y2]+f[x1-1][y1-1]-f[x1-1][y2]-f[x2][y1-1]
解题:
#include<iostream> using namespace std; typedef long long ll; ll n,m,q; const ll N = 1e3+10; ll f[N][N];//前缀和数组 ll a[N][N]; int main() {//数据录入cin >> n >> m >> q;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> a[i][j];}}//前缀和处理for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){f[i][j] = f[i-1][j] + f[i][j-1] - f[i-1][j-1] + a[i][j];}}//数据处理并输出while(q--){ll x1,x2,y1,y2;cin >> x1 >> y1 >> x2 >> y2;ll answer = f[x2][y2]+f[x1-1][y1-1]-f[x1-1][y2]-f[x2][y1-1];cout << answer << endl;}return 0; }
注意:
1.本题采取索引为1的存储方式:
其一是为了和题目给的索引对应
其二是为了避免进行边界检查,因为推导的公式中存在访问i-1或j-1的,如果从索引为0开始计算会出现越界访问-1的情况
2.本题需要采用long long 类型:因为题目中的数据范围是-1e9~1e9,这是很大的,如果进行运算很容易就超过int的存储范围
【模板】二维前缀和