【前缀和算法】--- 一维和二维前缀和模板

 Welcome to 9ilk's Code World

       

(๑•́ ₃ •̀๑) 个人主页:       9ilk

(๑•́ ₃ •̀๑) 文章专栏:    算法Journey  


本文开始,博主开始讲解有关前缀和的算法,本篇博客我们先来了解一下有关前缀和的两个模板。


🏠 一维前缀和模板

📌 题目内容

一维前缀和

📌题目解析

  • 数组的下标是从1开始的。
  • 数组中每个值的范围是−10^9 ≤ a[i] ≤ 10^9,因此我们需要考虑如果多个值相加用int可能溢出,可以考虑用long long.

📌算法原理

✏️ 思路一:暴力解法

 暴力解法很简单就是进行模拟,每次查询从L下标开始遍历直到到R下标。最坏情况是L是1下标,而R是n下标,n为数组长度。因此时间复杂度为O(q*n).

有没有什么优化的解法?

✏️ 思路二:前缀和

前缀和算tg法分为两步:1.预处理出来一个前缀和数组。2.使用前缀和数组。它可以用来快速求出数组中某一个连续区间的和。

  • 预处理出前缀和数组

假设有一个数组arr,同时有个相关联的数组dp,dp[i]表示的是arr数组[1,i]区间内所有值和。

我们发现,比如dp[3]是【1,3】区间值的和,那么就相当于是【1,2】区间的和+arr[3].

因此我们可以得出公式dp[i] = dp[i-1] + arr[i].

通过公式我们在遍历一遍数组的同时,就可以求出前缀和数组。

  • 使用前缀和数组

题目要我们求出[l,r]区间内值的和,由于我们提前求出了前缀和数组,我们发现所求区间 = 总和 - 前一段区间,因此【l,r】= dp[r] - dp[l-1],这个过程是很快的达到了O(1)

参考代码:

typedef long long ll;
int main() 
{
   int n = 0;
   int q = 0; //查询次数
   cin >> n >> q;
   vector<ll> v(n+1,0);
   vector<ll> dp(n+1,0);
   ll prev = 0;
   //获得前缀和数组
   //dp[i]表示的是从1到i区间值的总和
   for(int i = 1 ; i <= n ; i++)
   {
       cin >> v[i];
       dp[i] = dp[i-1] + v[i];
   } 
   //使用前缀和数组
   while(q--)
   {
     int l = 0;
     int r = 0;
     cin >> l >> r;
     cout << dp[r] - dp[l-1] << endl; 
   }
   return 0;
}
  • 细节问题

我们前缀和数组下标是从1开始的,如果下标从0开始,当求[0,2]区间的值之和时就转化成dp[2] - dp[-1]这个dp[-1]是个边界情况需要我们特殊处理且原本数组没有-1开始的;如果下标从1开始,当求[1,2]区间的值之和时转化成dp[2] - dp[0],对于dp[0]我们就容易将它处理为0即可

总结:前缀和数组下标从1开始,是为了处理边界情况。

🏠 二维前缀和数组

📌 题目内容

二维前缀和

📌 题目解析

  • 本题数据范围仍然过大,用int会有溢出的风险。
  • 题目要我们求的是以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的和。

📌 算法原理

✏️ 思路一:暴力解法

暴力解法也就是模拟从第一个点开始直接按照划分区域进行遍历,最坏情况是整个矩阵,时间复杂度是O(n*m*q).

✏️ 思路二:二维前缀和

  • 预处理出二维前缀和数组

假设有一个二维数组arr,dp数组是一个与它关联的数组。dp[i][j]表示以(1,1)为左上角,(i,j)为右上角形成的子矩阵中值之和。任取一块区域,假设D为(i,j)点,若我们要求dp[i][j]也就是求(1,1)到(i,j)区域的和,我们可以将这四部分相加,由于B和C不好求,我们可以利用A(dp[i-1][j-1])来间接求这两部分,但是不要忘记减去多进来的A。由于A+B和A+C在dp数组中分别对应的是dp[i-1][j]和dp[i][j-1],因此我们可以得到公式:

dp[ i ][ j ] = dp[ i-1 ][ j ] + dp[ i ][ j-1 ] + arr[ i ][ j ] - dp[ i-1][ j-1 ].

通过公式,我们在遍历二维数组时就可以求出对应的dp二维数组。

  • 使用二维前缀和数组

题目要我们求以(x1,y1)为左上角,(x2,y2)为右上角区域的值之和,也就是求区域D。因此D可以由整体减去A,B,C三部分,由于B和C不好求,所以我们利用A间接求。于是有D=(A+B+C+D) - (A+C) - (A+B) +A。对于A就是dp[x1][y1],A+B就是dp[x1-1][y2],A+C就是dp[x2][y1-1],于是得到公式:D = dp[x2][y2] - dp[x2][y1-1] - dp[x1-1][y2] + dp[x1-1][y1-1]。此时 我们由于提前得到的二维前缀和数组,我们能很快得出D的值,时间复杂度是O(1).

时间复杂度优化为了O(m*n) + O(q).

参考代码:

int main() 
{
    int n = 0; //行 
    int m = 0; //列
    int q = 0; //查询次数
    cin >> n >> m >> q;
    vector<vector<long long>> vv(n + 1);
    vector<vector<long long>> dp(n + 1);
    for (int i = 0; i <= n; i++)
    {
        vv[i].resize(m + 1, 0);
        dp[i].resize(m + 1, 0);
        if (i >= 1)
        {
            for (int j = 1; j <= m; j++)
            {
                cin >> vv[i][j];
            }
        }
    }

    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] + vv[i][j] - dp[i-1][j-1];
        }
    }

    while (q--)
    {
        int x1, x2, y1, y2 = 0;
        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;
}

总结:

1. 一维和二维前缀和数组下标都是从1开始。

2.当我们需要快速求出一段连续区间或区域时,可以考虑用前缀和数组,用前缀和数组间接求我们需要的。

3.我们可以根据场景推导出公式获得前缀和数组。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络】局域网LAN、广域网WAN、TCP/IP协议、封装和分用

文章目录 局域网 LAN广域网 WAN网络中的重要概念IP 地址端口号 认识协议协议分层是什么OSI 七层网络模型TCP/IP 五层网络模型&#xff08;或四层&#xff09;物理层传输层网络层数据链表层应用层网络设备所在分层 封装和分用[站在发送方视角]&#xff08;封装&#xff09;[站在…

邮票孔拼版制作方法

邮票孔拼版制作方法 拼版后的局部图:(中间用连接桥的方式&#xff0c;此方式能最少程度上减少残留) 2&#xff09;拼版后的效果图 3&#xff09;邮票孔拼版规则: 拼板与板间距1.2MM或者1.6MM 等邮票孔&#xff1a;8个0.55MM的孔,孔间距0.2MM加两排&#xff0c;邮票孔伸到…

linux服务 学习

服务&#xff08;Service&#xff09; 在Linux操作系统中&#xff0c;服务&#xff08;Service&#xff09;是一个基本概念&#xff0c;它通常指的是运行在后台的、持续提供特定功能或资源给系统内部组件或者网络上的客户端程序。 这些服务是系统正常运行和提供各种功能的关键…

【三维重建汇总】NeRF和GS重建中,如何排除干扰物?(提升质量)

汇总最近NeRF与GS提升质量的论文 文章目录 前言一、NeRF On-the-go&#xff1a;利用不确定性落地真实世界&#xff08;CVPR24&#xff09;摘要1.DINOv2特征的不确定性预测2.NeRF中干扰物去除的不确定性3.优化4. Dilated Patch 扩大采样5.实验结果 二、Pixel-GS:像素感知的梯度密…

关于nginx标准配置参数介绍

标准配置参数&#xff1a; user root;#配置用户或者组&#xff0c;默认为nobody worker_processes 4;#允许生成的进程数&#xff0c;默认为1 项目中nginx.conf配置文件 user root; worker_processes 4; //最大的进程数&#xff0c;要看服务器的内核是多少核的&#xff0…

Excel“取消工作表保护”忘记密码并恢复原始密码

文章目录 1.前言2.破解步骤3. 最终效果4.参考文献 1.前言 有时候别人发来的Excel中有些表格不能编辑&#xff0c;提示如下&#xff0c;但是又不知道原始密码 2.破解步骤 1、打开您需要破解保护密码的Excel文件&#xff1b; 2、依次点击菜单栏上的视图—宏----录制宏&#xf…

解决k8s分布式集群,子节点加入到主节点失败的问题

1.问题情况 Master主节点在 使用 kubeadm init 成功进行初始化后&#xff0c;如下所示 Your Kubernetes control-plane has initialized successfully!To start using your cluster, you need to run the following as a regular user:mkdir -p $HOME/.kubesudo cp -i /etc/k…

【Qt】 常用控件QLCDNumber

常用控件QLCDNumber QLCDNumber是一个专门用来显示数字的控件&#xff0c;类似于“老式计算机”的效果。 QLCDNumber的属性 属性说明 intValue QLCDNumber 显⽰的数字值(int). value QLCDNumber 显⽰的数字值(double). 和 intValue 是联动的. 例如给 value 设为 1.5, i…

玩转单例模式

目录 1. 饿汉式 2. 懒汉式 3. volatile解决指令重排序 4. 反射破坏单例模式 5. 枚举实现单例模式 6. 枚举实现单例模式的好处 7. 尝试反射破坏枚举 8. CAS实现单例模式 所谓单例模式&#xff0c;就是是某个类的实例对象只能被创建一次&#xff0c;单例模式有多种实现方…

【安全工具推荐-Search_Viewer资产测绘】

目录 一、工具介绍 二、工具配置 三、传送门 一、工具介绍 Search_Viewer&#xff0c;集Fofa、Hunter鹰图、Shodan、360 quake、Zoomeye 钟馗之眼、censys 为一体的空间测绘gui图形界面化工具&#xff0c;支持一键采集爬取和导出fofa、shodan等数据&#xff0c;方便快捷查看…

批发供应系统:提升效率与竞争力的关键

在当今复杂多变的商业环境中&#xff0c;批发供应系统作为连接生产商、分销商与零售商的重要纽带&#xff0c;其效率与智能化水平直接决定了供应链的运作效率与市场竞争力。随着信息技术的飞速发展&#xff0c;尤其是大数据、云计算、人工智能&#xff08;AI&#xff09;及物联…

基于HarmonyOS的宠物收养系统的设计与实现(一)

基于HarmonyOS的宠物收养系统的设计与实现&#xff08;一&#xff09; 本系统是简易的宠物收养系统&#xff0c;为了更加熟练地掌握HarmonyOS相关技术的使用。 项目创建 创建一个空项目取名为PetApp 首页实现&#xff08;组件导航使用&#xff09; 官方文档&#xff1a;组…

Qt系列之数据库(三)补充篇

一、数据库删除操作&#xff1a; 基本语法 DELETE FROM table_name WHERE [condition]; DELETE FROM ---- 关键字 table_name ---- 表名 WHERE ---- 条件的关键字 [condition] --- 条件表达式在这里插入代码片具体使用&#xff1a; QString sqlDelete QString("DELETE…

落地 DevOps,探索高效研发运营一体化解决方案

前言与概述 伴随着企业业务的快速发展&#xff0c;为了支撑业务发展&#xff0c;提高 IT 对业务的支撑能力建设。在研发工程协同方面&#xff0c;希望加强代码管理&#xff0c;实现持续构建、自动化测试、自动化部署、自动化运维&#xff0c;同时加强产品的安全和质量管理&…

ggplot阶截断坐标轴-gggap

目录 gggap包安装 功能查询 简单版使用代码 复杂版使用代码 gggap包安装 CRAN: Package gggap (-project.org) 手动下载安装 功能查询 > ?gggap > ?gggapDefine Segments in y-Axis for ggplot2 Description Easy-to-define segments in y-axis for ggplot2. …

React+Vis.js(05):节点的点击事件

文章目录 需求实现思路抽屉实现完整代码需求 双击节点,弹出右侧的“抽屉”,显示节点的详细信息 实现思路 vis.network提供了一个doubleClick事件,代码如下: network.on(doubleClick, function (properties) {// console.log(nodes);let id = properties

【数据结构】PTA 带头结点的链式表操作集 C语言

本题要求实现带头结点的链式表操作集。 函数接口定义&#xff1a; List MakeEmpty(); Position Find( List L, ElementType X ); bool Insert( List L, ElementType X, Position P ); bool Delete( List L, Position P ); 其中List结构定义如下&#xff1a; typedef struc…

STM32第十二节(中级篇):串口通信(第一节)——功能框图讲解

前言 我们在51单片机中就已经学习过了串口通信的相关知识点&#xff0c;那么我们现在在32单片机上进一步学习通信的原理。我们主要讲解串口功能框图以及串口初始化结构体以及固件库讲解。 STM32第十二节&#xff08;中级篇&#xff09;&#xff1a;串口通信&#xff08;第一节…

漏洞扫描的重要性,如何做好漏洞扫描服务

随着互联网技术的飞速发展&#xff0c;网络安全问题已成为不容忽视的重大挑战。其中&#xff0c;系统漏洞威胁作为最常见且严重的安全危险之一&#xff0c;对组织和个人的信息资产构成了巨大威胁。下面我们就来了解下漏洞扫描的好处、漏洞扫描的操作方法以及如何做好网络安全。…

使用 onBeforeRouteUpdate 组合式函数提升应用的用户体验

title: 使用 onBeforeRouteUpdate 组合式函数提升应用的用户体验 date: 2024/8/15 updated: 2024/8/15 author: cmdragon excerpt: 摘要&#xff1a;本文介绍如何在Nuxt 3开发中使用onBeforeRouteUpdate组合式函数来提升应用用户体验。通过在组件中注册路由更新守卫&#xf…