跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++java算法

算法模板精讲:一维与二维前缀和实现及原理

综述由AI生成一维与二维前缀和算法的原理与实现。通过预处理数组或矩阵,将区间查询时间复杂度优化至 O(1)。内容涵盖递推公式推导、边界处理技巧及 C++ 与 Java 代码模板,适用于矩阵区域求和等场景。重点讲解了二维前缀和中的容斥原理应用及坐标映射关系。

佛系玩家发布于 2026/3/15更新于 2026/4/265 浏览
算法模板精讲:一维与二维前缀和实现及原理

算法模板精讲:一维与二维前缀和

在处理区间求和问题时,如果涉及多次查询,暴力计算会导致超时。前缀和(Prefix Sum)是一种经典的预处理技巧,能将单次查询的时间复杂度从 O(N) 降低到 O(1)。本文将详细讲解一维和二维前缀和的核心逻辑、公式推导及代码实现。

一、一维前缀和

核心思路

假设我们有一个数组 arr,我们希望快速求出任意区间 [l, r] 内元素的和。

  1. 预处理:构建一个前缀和数组 dp。定义 dp[i] 为原数组下标 1 到 i 所有元素的累加和。
    • 递推公式:dp[i] = dp[i - 1] + arr[i]
    • 注意:为了处理边界方便,通常将数组下标从 1 开始,dp[0] 设为 0。
  2. 查询:当需要计算区间 [l, r] 的和时,利用容斥思想:
    • 区间和 = dp[r] - dp[l - 1]

代码实现

C++ 实现
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;
    
    // 使用 long long 防止求和溢出
    vector<long long> arr(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> arr[i];
    }

    // 预处理前缀和
    vector<long long> dp(n + 1, 0);
    for (int i = 1; i <= n; i++) {
        dp[i] = dp[i - ] + arr[i];
    }

    
     (m--) {
         l, r;
        cin >> l >> r;
        cout << dp[r] - dp[l - ] << endl;
    }
     ;
}
1
// 处理查询
while
int
1
return
0
Java 实现
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        if (!scan.hasNext()) return;
        
        int n = scan.nextInt();
        int q = scan.nextInt();
        
        // 使用 long 防止溢出
        long[] arr = new long[n + 1];
        long[] dp = new long[n + 1];
        
        for (int i = 1; i <= n; i++) {
            arr[i] = scan.nextInt();
        }
        
        for (int i = 1; i <= n; i++) {
            dp[i] = dp[i - 1] + arr[i];
        }
        
        while (q-- > 0) {
            int l = scan.nextInt();
            int r = scan.nextInt();
            System.out.println(dp[r] - dp[l - 1]);
        }
    }
}

性能说明:预处理阶段时间复杂度为 O(N),单次查询时间复杂度为 O(1),空间复杂度为 O(N)。


二、二维前缀和

核心思路

二维前缀和一维类似,但处理的是矩阵区域求和。目标是快速求出以 (row1, col1) 为左上角、(row2, col2) 为右下角的矩形区域内元素之和。

1. 预处理:构建前缀和矩阵

为了简化边界判断,我们在原矩阵上方和左方各补一行/一列 0。这样 dp[i][j] 表示从 (1, 1) 到 (i, j) 所围成矩形的元素总和。

文章配图

递推公式推导: dp[i][j] 的值等于当前元素加上其左侧和前侧的前缀和,但要注意重叠部分被加了两次,需要减去一次。 文章配图

公式如下: dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + matrix[i - 1][j - 1] (注:此处假设原矩阵下标从 0 开始,dp 表下标从 1 开始,需做坐标映射)

2. 查询:利用容斥原理

对于查询区域 (x1, y1) 到 (x2, y2),我们需要从大矩形中减去多余的部分。 文章配图

计算公式: Sum = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]

代码实现

C++ 实现
#include <iostream>
#include <vector>
using namespace std;

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    
    // 读入数据,下标从 1 开始
    vector<vector<int>> arr(n + 1, vector<int>(m + 1));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> arr[i][j];
        }
    }

    // 预处理二维前缀和
    vector<vector<long long>> dp(n + 1, vector<long long>(m + 1, 0));
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j];
        }
    }

    // 处理查询
    while (q--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        cout << dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1] << endl;
    }
    return 0;
}
Java 实现
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        if (!in.hasNext()) return;
        
        int n = in.nextInt();
        int m = in.nextInt();
        int q = in.nextInt();
        
        int[][] arr = new int[n + 1][m + 1];
        long[][] dp = new long[n + 1][m + 1];
        
        // 读入数据
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        
        // 处理前缀和矩阵
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + arr[i][j];
            }
        }
        
        // 处理查询
        while (q-- > 0) {
            int x1 = in.nextInt();
            int y1 = in.nextInt();
            int x2 = in.nextInt();
            int y2 = in.nextInt();
            System.out.println(dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] + dp[x1 - 1][y1 - 1]);
        }
    }
}

性能说明:预处理时间复杂度 O(N*M),单次查询 O(1)。建议在实际编码中手动推导一遍公式,加深理解。


总结

前缀和是解决区间求和问题的基础工具。掌握其核心在于理解'预处理换查询'的思想,以及二维情况下的容斥原理应用。在遇到大量区间查询且数据范围允许预处理时,优先考虑此方案。

目录

  1. 算法模板精讲:一维与二维前缀和
  2. 一、一维前缀和
  3. 核心思路
  4. 代码实现
  5. C++ 实现
  6. Java 实现
  7. 二、二维前缀和
  8. 核心思路
  9. 1. 预处理:构建前缀和矩阵
  10. 2. 查询:利用容斥原理
  11. 代码实现
  12. C++ 实现
  13. Java 实现
  14. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • 💰 8折买阿里云服务器限时8折购买
  • 🦞 5分钟部署阿里云小龙虾了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 长亭 Xray Web 漏洞扫描器使用指南
  • Java Web 前端基础:HTML 核心知识点总结
  • 树莓派 4B 连接大疆 M300 RTK 无人机 PSDK 开发指南
  • Win10 禁用 Microsoft 365 Copilot 弹窗的 6 种方案
  • Spring MVC 响应处理:页面、数据与状态码配置详解
  • 使用 Servlet 快速构建 Web 应用原型
  • ClawdBot 环境部署:vLLM 后端、Web 控制台与设备授权解析
  • 飞算 JavaAI 专业版在 Java 微服务重构中的效率提升实践
  • 文心一言 4.5 开源模型 ERNIE-4.5-0.3B 轻量化部署与优化
  • 企业级新能源充电系统管理架构设计与实现
  • AI 辅助编程的边界探索:当 Copilot 学会写测试
  • DAG 动态规划:嵌套矩形与地铁间谍问题
  • 哈希(Hash)核心概念与 C++ 应用
  • 使用 AI 在 Figma 中自动生成 UI 设计稿
  • AI 产品经理职业发展路径与核心技术能力解析
  • OpenClaw 开源 AI 智能体本地部署与使用教程
  • 阿里推出 AI 编程插件 Qoder,JetBrains 集成体验一周评测
  • C++ STL 常用算法详解:序列、排序与数值处理
  • ROS2 中的 TF 系统:机器人坐标系管理
  • C++ 矩阵翻转与 n*n 矩阵旋转实现

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online