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

【模板】二维前缀和

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()

算法及复杂度

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

相关推荐

脾气小祖宗:这简历摸到都得狠狠地消毒液洗手😂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 你的mentor是什么样的人? #
4219次浏览 30人参与
# 你觉得mentor喜欢什么样的实习生 #
10469次浏览 293人参与
# 平安产险科技校招 #
2413次浏览 0人参与
# 帮我看看,领导说这话什么意思? #
6386次浏览 26人参与
# 没有家庭托举的我是怎么找工作的 #
12454次浏览 160人参与
# 怎么给家人解释你的工作? #
1460次浏览 16人参与
# 智慧芽求职进展汇总 #
18088次浏览 108人参与
# 求职低谷期你是怎么度过的 #
5300次浏览 93人参与
# 26届秋招公司红黑榜 #
12533次浏览 43人参与
# 从哪些方向判断这个offer值不值得去? #
6627次浏览 95人参与
# 同bg的你秋招战况如何? #
158834次浏览 927人参与
# 度小满求职进展汇总 #
10130次浏览 53人参与
# 实习必须要去大厂吗? #
146706次浏览 1541人参与
# 校招泡的最久的公司是哪家? #
4669次浏览 22人参与
# 你有哪些缓解焦虑的方法? #
37188次浏览 835人参与
# 面试紧张时你会有什么表现? #
1740次浏览 21人参与
# 你喜欢工作还是上学 #
77599次浏览 860人参与
# 入职第一天,你准备什么时候下班 #
85497次浏览 467人参与
# 秋招想进国企该如何准备 #
97728次浏览 487人参与
# 简历无回复,你会继续海投还是优化再投? #
103595次浏览 819人参与
# 机械人的工作环境真的很差吗 #
25049次浏览 119人参与
# 独居后,你的生活是更好了还是更差了? #
28136次浏览 263人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务