解题思路

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

算法及复杂度

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