【CSP考点回顾】前缀和数组

一、一维数组前缀和

前缀和算法是一种用于处理数组的技术,它可以快速计算任何连续子数组的和。适合在多次查询中需要求解多个范围和的情况。使用前缀和算法可以将每次求和的时间复杂度从 O(n) 降低到 O(1)。

  • 前缀和的思想是创建一个新数组 A r r Arr Arr p r e A r r [ i ] preArr[i] preArr[i] 记录 A r r [ 0... i − 1 ] Arr[0...i-1] Arr[0...i1] 的累加和,如图:

请添加图片描述

  • 那么,求索引区间 [ 1 , 4 ] [1,4] [1,4] 内所有元素之和,可以通过 p r e A r r [ 5 ] − p r e A r r [ 1 ] preArr[5]-preArr[1] preArr[5]preArr[1] 得出。这样,便只需要做一次减法运算,避免了每次进行 for 循环调用,时间复杂度为常数 O ( 1 ) O(1) O(1)

  • 前缀和算法广泛用于处理数组求和问题,特别是当需要多次求解不同子数组的和时,它可以大大减少计算时间。

  • 例如,班上有若干同学,每个同学有一个期末考试的成绩(满分100分),那么请实现输入任意一个分数段,返回有多少同学的成绩在这个分数段内。

vector<int>scores; // 存储所有分数
vector<int>cnt(100 + 1, 0); //满分为100
for (auto& it : scores) // 记录每个分数有多少同学
{cnt[it]++;
}
for (int i = 1; i < scores.size(); i++) // 构造前缀和
{cnt[i] += cnt[i - 1];
}
// 利用前缀和数组进行差分查询

二、二维数组的前缀和

二维数组的前缀和是前缀和概念在二维空间的扩展。这个技巧通常用于处理二维数组上的区域和查询,特别适合于频繁查询数组特定子矩阵(子区域)内元素的总和的情况

1.二维前缀和数组构建步骤:

  1. 初始化 p r e A r r 2 preArr2 preArr2 的所有元素为 0。

  2. 遍历原始二维数组 A r r 2 Arr2 Arr2,更新 p r e A r r 2 preArr2 preArr2 中的值。对于 p r e A r r 2 preArr2 preArr2 中的每个元素(位于 ( i , j ) (i, j) (i,j)),其值由以下元素决定:

    • 原数组 A r r 2 Arr2 Arr2 ( i − 1 , j − 1 ) (i - 1, j - 1) (i1,j1) 的值(因为 p r e A r r 2 preArr2 preArr2 A r r 2 Arr2 Arr2 多了一行和一列)。
    • p r e A r r 2 preArr2 preArr2 中上方 ( i − 1 , j ) (i - 1, j) (i1,j) 的前缀和。
    • p r e A r r 2 preArr2 preArr2 中左侧 ( i , j − 1 ) (i, j - 1) (i,j1) 的前缀和。
    • p r e A r r 2 preArr2 preArr2 中左上角 ( i − 1 , j − 1 ) (i - 1, j - 1) (i1,j1) 的前缀和,因为它被加了两次(在上方和左侧的和中),所以需要减去。
  3. p r e A r r 2 [ i ] [ j ] preArr2[i][j] preArr2[i][j] 的计算公式为:
    p r e A r r 2 [ i ] [ j ] = A r r 2 [ i − 1 ] [ j − 1 ] + p r e A r r 2 [ i − 1 ] [ j ] + p r e A r r 2 [ i ] [ j − 1 ] − p r e A r r 2 [ i − 1 ] [ j − 1 ] preArr2[i][j] = Arr2[i - 1][j - 1] + preArr2[i - 1][j] + preArr2[i][j - 1] - preArr2[i - 1][j - 1] preArr2[i][j]=Arr2[i1][j1]+preArr2[i1][j]+preArr2[i][j1]preArr2[i1][j1]

【注意】对于 p r e A r r 2 preArr2 preArr2 的第一行和第一列,我们将它们保持为 0,这样可以简化边界条件的处理。

2.使用二维前缀和数组数组:

  • 我们可以快速计算出原数组中任意子矩阵 ( x 1 , y 1 ) (x1, y1) (x1,y1) ( x 2 , y 2 ) (x2, y2) (x2,y2) 的和,通过以下公式:
    s u m = p r e A r r 2 [ x 2 + 1 ] [ y 2 + 1 ] − p r e A r r 2 [ x 1 ] [ y 2 + 1 ] − p r e A r r 2 [ x 2 + 1 ] [ y 1 ] + p r e A r r 2 [ x 1 ] [ y 1 ] sum = preArr2[x2 + 1][y2 + 1] - preArr2[x1][y2 + 1] - preArr2[x2 + 1][y1] + preArr2[x1][y1] sum=preArr2[x2+1][y2+1]preArr2[x1][y2+1]preArr2[x2+1][y1]+preArr2[x1][y1]
    这里 ( x 1 , y 1 ) (x1, y1) (x1,y1) 是子矩阵左上角的坐标, ( x 2 , y 2 ) (x2, y2) (x2,y2) 是子矩阵右下角的坐标。注意,因为 p r e A r r 2 preArr2 preArr2 的定义,我们需要使用加一的索引来引用原始 A r r 2 Arr2 Arr2 中的相应区域。

3.举例

原始二维数组 Arr2:

123
456
789

二维前缀和数组 preArr2:

0000
0136
051221
0122745

代码示例

#include <iostream>
#include <vector>using namespace std;int main() {// 定义初始二维数组 Arr2vector<vector<int>> Arr2 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};// 获取数组的行数和列数int m = Arr2.size();int n = Arr2[0].size();// 构建二维前缀和数组 preArr2vector<vector<int>> preArr2(m + 1, vector<int>(n + 1, 0));for (int i = 1; i <= m; ++i) {for (int j = 1; j <= n; ++j) {preArr2[i][j] = Arr2[i - 1][j - 1] + preArr2[i - 1][j] + preArr2[i][j - 1] - preArr2[i - 1][j - 1];}}// 输出构建完成的二维前缀和数组for (int i = 0; i <= m; ++i) {for (int j = 0; j <= n; ++j) {cout << preArr2[i][j] << " ";}cout << "\n";}return 0;
}

本文部分内容参考自:【labuladong】前缀和/差分数组技巧精讲

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

递增三元组(第九届蓝桥杯)

文章目录 题目原题链接思路分析二分做法1二分做法2双指针做法前缀和解法 题目 原题链接 递增三元组 思路分析 由时间复杂度可知需要至少优化到 O ( n l o g n ) O(nlogn) O(nlogn)才行 而纯暴力枚举三个数组的话&#xff1a; O ( n 3 ) O(n^3) O(n3) 可以考虑将b[]作为标志&…

RabbitMQ 交换器

RabbitMQ 交换器 官方例子 http://www.rabbitmq.com/getstarted.html direct 如上图所示&#xff0c;两个队列绑定到了direct交换器上&#xff0c;第一个队列绑定的 binding key 为 orange &#xff0c;第二个队列有两个绑定&#xff0c;分别是 black 和 green 。 如上图所示…

基础小白快速入门web前端开发技术------>web概述

Web概述 我们在编程的学习中&#xff0c;随着学习的深入&#xff0c;我们会理解到WEB这个东西&#xff0c;那么 web究竟是个啥&#xff0c;到底该咋用&#xff1f; web&#xff0c;是网站的英文意思&#xff0c;又被称作“下一代Web3.0&#xff0c;互联网”&#xff0c;是在We…

vue在线查看pdf文件

1.引入组件 npm install --save vue-pdf2、pdf组件页面模板 <template><div class"scrollBox" ><el-dialog :visible.sync"open" :top"1" width"50%" append-to-body><div slot"title"><el…

混沌工程-经典案例分享

目录 前言 案例 1、强弱依赖不合理 2、预案不生效 3、异常数据不兼容 4、监控体系缺陷 5、系统缺整体架构设计 总结 前言 我们公司从启动混沌工程到现在已经几乎覆盖了线上的所有核心业务&#xff0c;先后进行过2000次演练共挖掘出120个漏洞。这些漏洞有些得了及时修复…

DevEco Studio编译时候自动生成js、js.map文件导致项目无法运行

这算是开发工具的bug吧&#xff0c;估计后期能修复。 解决办法&#xff0c;手动删除.js、.js.map文件即可&#xff1b; 文件太多&#xff0c;删除很麻烦&#xff0c;有个大佬写了个插件&#xff0c;可一键删除&#xff1a;ArkCompilerSupport DevEco Studio 运行项目有时会自动…

二叉树进阶leetcode

606. 根据二叉树创建字符串 要点&#xff1a;前序遍历&#xff0c;当左子树为空时&#xff0c;右结点有数字时要给左边加括号 class Solution { public:string tree2str(TreeNode* root) {string s;//创建一个字符串if(rootnullptr){return s;}sto_string(root->val);//保存…

网络、网络协议模型、UDP编程——计算机网络——day01

今天来到了网络编程&#xff0c;主要讲了网络、网络协议模型以及UDP编程 网络 网络主要是进行&#xff1a;数据传输和数据共享 网络协议模型 OSI协议模型应用层 实际发送的数据表示层 发送的数据是否加密会话层 是否建立会话连接传…

调研图基础模型(Graph Foundation Models)

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 图基础模型&#xff08;Graph Foundation Models&#xff0c;简称 GFMs&#xff09; 是一种经过预训练的图大模型&#xff0c;旨在处理不同领域的图数据和任务。让我们详细探讨一下这个概念。 Github …

uniapp让输入框保持聚焦状态,不会失去焦点

使用场景&#xff1a;当输入框还有发送按钮的时候&#xff0c;点击发送希望软键盘不消失&#xff0c;还可以继续输入&#xff0c;或者避免因输入图片标签造成的屏闪问题 多次尝试后发现一个很实用的方法&#xff0c;适用input输入框和editor输入框 解决办法&#xff1a;把cli…

AXI4总线解析

一、读地址 AWVALID和AWREADY同时为高时&#xff0c;在这个上升沿&#xff0c;图中黄线&#xff0c;将接下来的数据写入地址40000000中。 在

基于状态机的按键消抖实现

摸鱼记录 Day_14 !(^O^)y review 在day_13中以按键状态判断为例学习了状态分析基于状态机的按键消抖原理-CSDN博客 分析得到了下图&#xff1a; 今日任务&#xff1a;完成此过程 !(^O^)y 小梅哥对应视频&#xff1a; 15B 基于状态机的按键消抖Verilog实现_哔哩哔哩…

DataFunSummit 2023:洞察现代数据栈技术的创新与发展(附大会核心PPT下载)

随着数字化浪潮的推进&#xff0c;数据已成为企业竞争的核心要素。为了应对日益增长的数据挑战&#xff0c;现代数据栈技术日益受到业界的关注。DataFunSummit 2023年现代数据栈技术峰会正是在这样的背景下应运而生&#xff0c;汇聚了全球数据领域的精英&#xff0c;共同探讨现…

Linux 文件操作命令

1 文件与目录操作 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录cd ../.. 返回上两级目录cd - 返回上次所在目录cp file1 file2 将file1复制为file2cp -a dir1 dir2 复制一个目录 cp -a /tmp/dir1 . 复制一个…

【Qt】初识Qt

文章目录 一. 行业岗位介绍二. 什么是客户端&#xff1f;三. GUI 开发的各自技术方案四. 什么是框架&#xff1f;五. Qt 的发展史五. Qt 支持的系统六. Qt 的优点 一. 行业岗位介绍 二. 什么是客户端&#xff1f; 既然 Qt 是用来进行客户端开发的&#xff0c;那我们就要了解什…

如何保证ES和数据库的数据一致性?

在业务中&#xff0c;我们通常需要把数据库中的数据变更同步到ES中&#xff0c;那么如何保证数据库和ES的一致性呢&#xff1f;通常有以下几种做法&#xff1a; 双写 在代码中&#xff0c;对数据库和ES进行双写&#xff0c;并且先操作本地数据库&#xff0c;后操作ES&#xff…

Ubuntu20.04安装并配置vscode

Ubuntu20.04安装并配置vscode vscode安装miniconda安装创建虚拟python3.8环境pytorch和匹配的cuda安装 vscode安装 VSCode可以通过 Snapcraft 商店或者微软源仓库中的一个 deb 软件包来安装。 我们这里选用安装VSCode snap版&#xff0c;打开你的终端(CtrlAltT)并且运行下面的…

px2rem实现vue项目响应式布局

第一步 首先需要在项目中安装px2rem插件 npm install postcss-px2rem px2rem-loader --save 第二步 在项目src目录下新建util文件夹&#xff0c;在util文件夹下新建rem.js文件&#xff0c;内容如下&#xff1a; // rem等比适配配置文件 // 基准大小 const baseSize 14 //…

【机器学习300问】27、什么是决策树?

〇、两个预测任务 &#xff08;1&#xff09;任务一&#xff1a;银行预测偿还能力 当前&#xff0c;某银行正致力于发掘潜在的放贷用户。他们掌握了每位用户的三个关键特征&#xff1a;房产状况、婚姻状况以及年收入。此外&#xff0c;银行还拥有过往这些用户的债务偿还能力的…

Linux系统——LVS-DR群集部署及拓展

目录 引言 1.LVS的工作模式及其工作过程 2.列举出LVS调度算法 3.LVS调度常见算法&#xff08;均衡策略&#xff09; 3.1固定调度算法:rr&#xff0c;wrr&#xff0c;dh&#xff0c;sh 3.2动态调度算法:wlc&#xff0c;lc&#xff0c;lblc 4.LVS三种工作模式区别 一、I…