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

【模板】二维前缀和

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

解题思路

  1. 问题分析:

    • 需要多次查询矩阵子区域的和
    • 直接累加会导致时间复杂度
    • 可以使用二维前缀和优化到
  2. 二维前缀和优化:

    • 预处理矩阵,计算二维前缀和
    • 对于查询 ,结果为:
    • 预处理时间 ,每次查询
  3. 实现要点:

    • 注意前缀和可能超出 范围,使用
    • 注意输入的下标从 开始
    • 使用快速输入输出优化读写时间

代码

#include <iostream>
#include <vector>
using namespace std;

int main() {
    ios::sync_with_stdio(false);  // 优化输入输出
    cin.tie(0);
    
    int n, m, q;
    cin >> n >> m >> q;
    
    // 构建二维前缀和数组,多加一行一列便于计算
    vector<vector<long long>> prefix(n + 1, vector<long long>(m + 1, 0));
    
    // 读入矩阵并计算前缀和
    for(int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) {
            int x;
            cin >> x;
            // 二维前缀和公式
            prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + x;
        }
    }
    
    // 处理查询
    while(q--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        // 计算子矩阵的和
        long long sum = prefix[x2][y2] - prefix[x1-1][y2] - prefix[x2][y1-1] + prefix[x1-1][y1-1];
        cout << sum << "\n";
    }
    
    return 0;
}
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(System.out);
        
        String[] line = br.readLine().split(" ");
        int n = Integer.parseInt(line[0]);
        int m = Integer.parseInt(line[1]);
        int q = Integer.parseInt(line[2]);
        
        // 构建二维前缀和数组
        long[][] prefix = new long[n + 1][m + 1];
        
        // 读入矩阵并计算前缀和
        for(int i = 1; i <= n; i++) {
            line = br.readLine().split(" ");
            for(int j = 1; j <= m; j++) {
                int x = Integer.parseInt(line[j-1]);
                prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + x;
            }
        }
        
        // 处理查询
        while(q-- > 0) {
            line = br.readLine().split(" ");
            int x1 = Integer.parseInt(line[0]);
            int y1 = Integer.parseInt(line[1]);
            int x2 = Integer.parseInt(line[2]);
            int y2 = Integer.parseInt(line[3]);
            
            long sum = prefix[x2][y2] - prefix[x1-1][y2] - prefix[x2][y1-1] + prefix[x1-1][y1-1];
            out.println(sum);
        }
        
        out.flush();
        br.close();
    }
}
def main():
    # 读取输入
    n, m, q = map(int, input().split())
    
    # 构建二维前缀和数组
    prefix = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 读入矩阵并计算前缀和
    for i in range(1, n + 1):
        row = list(map(int, input().split()))
        for j in range(1, m + 1):
            prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + row[j-1]
    
    # 处理查询
    for _ in range(q):
        x1, y1, x2, y2 = map(int, input().split())
        # 计算子矩阵的和
        sum_region = prefix[x2][y2] - prefix[x1-1][y2] - prefix[x2][y1-1] + prefix[x1-1][y1-1]
        print(sum_region)

if __name__ == "__main__":
    main()

算法及复杂度

  • 算法:二维前缀和
  • 时间复杂度:预处理 ,查询 ,总体
  • 空间复杂度:,用于存储二维前缀和数组
全部评论

相关推荐

06-02 15:53
阳光学院 Java
点赞 评论 收藏
分享
06-27 12:30
延安大学 C++
实习+外包,这两个公司底层融为一体了,如何评价呢?
一表renzha:之前面了一家外包的大模型,基本上都能答出来,那面试官感觉还没我懂,然后把我挂了,我都还没嫌弃他是外包,他把我挂了……
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务