题解 | #【模板】二维前缀和#

【模板】二维前缀和

http://www.nowcoder.com/practice/99eb8040d116414ea3296467ce81cbbc

思路是用一个二维数组sum来储存(0, 0)到该点所形成的子矩阵中所有数的和。即sum.at(i).at(j)储存着以(0,0)(i,j)为反对角线的矩阵的所有元素的和。
当要计算(x1, y1)与(x2, y2)所形成的矩阵中所有元素的和时,只需要用(0, 0)(x2, y2)这个大的矩形,减去(0, 0)(x1 - 1, y2)和(0, 0)(x2, y1 - 1)这两个矩形。当x1或y1为0时需分类讨论。

这种做法的时间复杂度主要体现在建立sum数组上,建立sum时用到了三重循环,时间复杂度在O(nm)之上。空间复杂度为O(nm)。
时间复杂度过高这个问题在提交时暴露无遗。此时我开始意识到我的做法可能出问题了。
alt
但是在看了别的同学的做法后发现思路基本一直,仅在实现的具体细节上有所差异。可能确实是代码中有些冗余,且没有选择效率较高的写法,还有优化空间。

#include <iostream>
#include <vector>

using namespace std;

int main(){
    int n, m, q;
    cin >> n >> m >>q;
    vector<int> col(m, 0);
    vector<vector<int>> matrix(n,col);
    for(int i = 0;i < n;i++){
        for(int j = 0;j < m;j++){
            cin >> matrix.at(i).at(j);
        }
    }
    vector<long long> scol(m, 0);
    vector<vector<long long>> sum(n,scol);
    for(int i = 0;i < n;i++){
        for(int j = 0;j < m;j++){
            if(j == 0 && i == 0){
                sum.at(i).at(j) = matrix.at(i).at(j);
            }
            else if(i == 0){
                sum.at(i).at(j) = sum.at(i).at(j - 1) + matrix.at(i).at(j);
            }
            else if(j == 0){
                sum.at(i).at(j) = sum.at(i - 1).at(j) + matrix.at(i).at(j);
            }
            else{
                sum.at(i).at(j) = sum.at(i).at(j - 1);
                for(int k = 0;k < i + 1;k++){
                    sum.at(i).at(j) += matrix.at(k).at(j);
                }
            }
        }
    }
    for(int i = 0;i < q;i++){
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        x1--;
        y1--;
        x2--;
        y2--;
        long long res;
        if(x1 == x2 && y1 == y2){
            res = matrix.at(x1).at(y1);
        }
        else if(!x1 && !y1){
            res = sum.at(x2).at(y2);
        }
        else if(x1 && !y1){
            res = sum.at(x2).at(y2) - sum.at(x1 - 1).at(y2);
        }
        else if(!x1 && y1){
            res = sum.at(x2).at(y2) - sum.at(x2).at(y1 - 1);
        }
        else if(x1 && y1){
            res = sum.at(x2).at(y2) - sum.at(x2).at(y1 - 1) - sum.at(x1 - 1).at(y2) + sum.at(x1 - 1).at(y1 - 1);
        }
        cout << res << endl;
    }
    return 0;
}
全部评论

相关推荐

10-06 12:46
门头沟学院 Java
跨考小白:定时任务启动
点赞 评论 收藏
分享
感性的干饭人在线蹲牛友:🐮 应该是在嘉定这边叭,禾赛大楼挺好看的
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务