算法基础之二分与前缀和 day 6

news2024/11/17 15:28:07

文章目录

    • 二分
      • 第一类
      • 第二类
    • 前缀和
      • 原题链接
      • 题目描述
        • 输入格式
        • 输出格式
        • 数据范围
        • 输入样例:
        • 输出样例:
      • 题目分析
      • 示例代码

二分

二分法是我们在高中数学就学习过的一种思想,他也是一种效率较高的查找算法,在编写代码的过程中,初学者很容易就会陷入死循环

二分的基本步骤如下

第一步是需要确定一个区间,使得我们的目标值一定是在区间中出现的

第二步需要确定一个性质,使得这个性质满足两点,第一点是可以根据这个性质把这个区间分为左和右连续的两段,第二点是我们最终的答案一定是二分的某一个分界点(绝大多数)

整数二分是很容易出现死循环的一种情况,因为整数是离散的,因此对应的答案在边界的情况也是两种

屏幕截图 2024-01-06 151802.png

其实相对应的,我们也可以将二分分为两大类,一种是答案在左边的终点,另一种是答案在右边的起点

我们来具体看一下这两种问题是如何二分的

第一类

目标值在红色区间的右端点

我们把区间进行标注,如图

屏幕截图 2024-01-06 152155.png

M是L和R的中点,其实就把区间[L,R]分成[L,M-1]和[M,R]

分成两段之后,我们只需要判断M的颜色(性质),如果是在红色区间,就说明目标值一定在绿色区间[M,R]内,否则说明目标值在红色区间[L,M-1]内

对应到代码上,我们可以这样写

while (L < R)
{
    M = (L + R + 1) / 2;
    if (M == '红')
        L = M;
    else
        R = M - 1;
}

这里需要注意的就是,当答案在左边区间的最后一位时,由于C/C++会自动下取整,这里算中点时就需要补上1,这样就不会漏判(死循环)了,当然这里也可以更改判断条件(例如L<=R),同样也不会出现死循环

这里有个简单的判断是否需要补上1,就是看我们在判断的时候如果写的是L=M,加上1就可以了

第二类

目标值是绿色区间的左端点

将[L,R]分成[L,M]和[M+1,R],如果M是绿色,说明目标值在红色区间[L,M],否则就是在绿色区间[M+1,R]

这里我们可以给出相应的代码

while (L < R)
{
    M = (L + R) / 2;
    if (M == '绿')
        R = M;
    else
        L = M + 1;
}

同样的,我们也是只要看判断之后的赋值语句即可,当L = M时,则需要加上1,当R = M时,则不需要加

前缀和

前缀和其实是一种快捷的求和的思想,是用于求一个静态区间的任意位置之间的所有数的和的思想

这里我们直接结合最基础的例题来理解

原题链接

795. 前缀和

题目描述

输入一个长度为 n 的整数序列。

接下来再输入 m 个询问,每个询问输入一对 l,r。

对于每个询问,输出原序列中从第 l 个数到第 r 个数的和。

输入格式

第一行包含两个整数 n 和 m。

第二行包含 n 个整数,表示整数数列。

接下来 m 行,每行包含两个整数 l 和 r,表示一个询问的区间范围。

输出格式

共 m 行,每行输出一个询问的结果。

数据范围

1≤l≤r≤n,
1≤n,m≤100000,
−1000≤数列中元素的值≤1000

输入样例:
5 3
2 1 3 6 4
1 2
1 3
2 4 
输出样例:
3
6
10 

题目分析

这里就是给出一个静态序列,有m次询问,每次给一对l和r,需要分别输出从l到r的总和

如果我们暴力做的话,就是每一次都需要从l加到r,并且每一次循环都是O(n)的时间复杂度

一旦当询问次数较大时,时间效率就会非常低

那么这时我们就会需要用到前缀和的思想,他非常的基础和重要,也是笔者最先开始学习的算法之一

我们把之前的那个静态序列标记为 a i a_i ai,表示第i项,然后我们来构建一个新的序列 s i s_i si,代表他是原序列中前i个数字的和

其中 s i = a 1 + a 2 + ⋯ + a i s_i = a_1 + a2 + \dots + a_i si=a1+a2++ai

特殊规定 s 0 = 0 s_0 = 0 s0=0

这样我们就可以发现一个规律

s i = s i − 1 + a i s_i = s_{i-1} + a_i si=si1+ai

我们可以根据这个公式递推出s序列中的所有数字

for(int i = 1; i <= n; i++)
{
    s[i] = s[i-1] + a[i];
}

这一步骤就叫做前缀和,也是我们之后求和的预处理工作

当我们想算从l到r的和时可以这样 a l + a l + 1 + a l + 2 + ⋯ + a r a_l + a_{l+1} + a_{l+2} + \dots + a_r al+al+1+al+2++ar

= a 1 + a 2 + ⋯ + a l − 1 + a l + a l + 1 + a l + 2 + ⋯ + a r − a 1 − a 2 − ⋯ − a l − 1 = a_1 + a_2 + \dots + a_{l-1} + a_l + a_{l+1} + a_{l+2} + \dots + a_r - a_1 - a_2 - \dots - a_{l-1} =a1+a2++al1+al+al+1+al+2++ara1a2al1

= s r − s l − 1 = s_r - s_{l-1} =srsl1

所以当我们预处理结束之后,我们只需要计算两个数的差即可,这样的时间复杂度就达到了O(1),是质的飞跃

对于计算区间和还有其他的方法,例如树状数组和线段树,这个我们以后会讲解,而对于前缀和来说,他的局限性就在于序列只能是静态的序列,一旦其中的某个数值被修改,就需要重新计算前缀和,而树状数组和线段树是可以实现边查边算的

示例代码

#include<iostream>
using namespace std;

const int N = 1e5+10; // 数据范围
int n,m;
long long arr[N]; // 原数组
long long pre[N]; // 前缀和数组

int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++) // 数据输入
    {
        cin>>arr[i];
        pre[i] = pre[i-1] + arr[i]; // 前缀和初始化
    }
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        cout<<pre[r] - pre[l-1]<<'\n';
    }
    return 0;
}

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

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

相关文章

关于“Python”的核心知识点整理大全64

目录 20.2.15 确保项目的安全 settings.py 20.2.16 提交并推送修改 20.2.17 创建自定义错误页面 1. 创建自定义模板 500.html settings.py settings.py 注意 views.py 20.2.18 继续开发 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xff1a…

基于 Python+Neo4j+医药数据,构建了一个知识图谱的自动问答系统

知识图谱是目前自然语言处理的一个热门方向。目前知识图谱在各个领域全面开花&#xff0c;如教育、医疗、司法、金融等。 本项目立足医药领域&#xff0c;以垂直型医药网站为数据来源&#xff0c;以疾病为核心&#xff0c;构建起一个包含7类规模为4.4万的知识实体&#xff0c;…

16.顺子日期(14)

题目 public class Main {public static boolean isLegal(String date) {int l 0;int n date.length();while(l<(n-3)) {int t1 (int)Integer.valueOf(date.substring(l,l1));int t2 (int)Integer.valueOf(date.substring(l1,l2));int t3 (int)Integer.valueOf(date.s…

案例介绍|钡铼助力2023年全国职业院校技能大赛工业网络智能控制与维护赛项

如今&#xff0c;越来越多的企业开始意识到数字制造和工业物联网已经成为工业自动化中大规模生产的核心驱动力。这其中&#xff0c;工业网络作为基础设施&#xff0c;是实现工厂设备联网与数据采集&#xff0c;建设数字工厂的基础和前提&#xff0c;甚至成为关乎数字工厂能否真…

C++ 类的内存分布

文章目录 1 . 前言2 . 无继承&#xff0c;无虚函数3 . 无继承&#xff0c;有虚函数4 . 单一继承&#xff0c;无虚函数5 . 单一继承&#xff0c;有虚函数&#xff0c;虚析构6 . 多重继承7 . 菱形继承8 . 虚拟继承9 . 总结 【极客技术传送门】 : https://blog.csdn.net/Engineer_…

CentOS:docker容器日志清理

1.先查看磁盘空间 df -h 2.找到容器的containerId-json.log文件,并清理 find /var/lib/docker/containers/ -name *-json.log |xargs du -sh 3、可以根据需求清理对应日志也可以清理数据大的日志 $ cat /dev/null > /var/lib/docker/containers/dbaee0746cc6adad3768b4ef…

Java快速排序希尔排序归并排序

快速排序算法 快速排序的原理&#xff1a;选择一个关键值作为基准值。比基准值小的都在左边序列&#xff08;一般是无序的&#xff09;&#xff0c;比基准值大的都在右边&#xff08;一般是无序的&#xff09;。一般选择序列的第一个元素。 一次循环&#xff1a;从后往前比较&…

软件测试|什么是Python构造方法,构造方法如何使用?

构造方法&#xff08;Constructor&#xff09;是面向对象编程中的重要概念&#xff0c;它在创建对象时用于初始化对象的实例变量。在Python中&#xff0c;构造方法是通过特殊的名称__init__()来定义的。本文将介绍Python构造方法的基本概念、语法和用法。 什么是构造方法&…

Qt添加资源文件

ui->setupUi(this);//1. 使用本地文件&#xff1a;ui->actionasdasdas->setIcon(QIcon("本地绝对路径"));ui->actiona1->setIcon(QIcon("C:/Users/满满/Desktop/output/picture/1.jpg"));//2. 使用资源文件&#xff1a;ui->actionasdasd…

二叉树基础oj练习(单值二叉树、相同的树、二叉树的前序遍历)

讲了这么多数据结构相关的知识(可以看我的数据结构文章专栏): 抓紧刷题巩固一下了 目录 1.单值二叉树 题目描述 思路1 代码1 思路2 代码2 2.相同的树 题目描述 思路 代码 3.二叉树的前序遍历 代码 思路 1.单值二叉树 965. 单值二叉树 - 力扣&#xff08;LeetCod…

NVM NodeJs版本管理 通关宝典

NVM NodeJs版本管理 通关宝典&#x1f3f9; 文章目录 NVM NodeJs版本管理 通关宝典&#x1f3f9;一、NVM是什么二、开始使用NVM三、NVM 命令速查四、手动安装特定Node版本(Windows)&#x1f644;4.1 NVM for windows 运行机制4.2 手动安装流程 五、切换 NVM 下载镜像源六、常见…

docker拉取镜像提示 remote trust data does not exist for xxxxxx

1、How can I be sure that I am pulling a trusted image from docker 2、docker: you are not authorized to perform this operation: server returned 401. 以上两个问题可以试试以下解决办法 DOCKER_CONTENT_TRUSTfalse 本人是使用jenkins部署自己的项目到docker容器出现…

【技巧】IDEA 使用小技巧(三)

IDEA 使用小技巧&#xff08;三&#xff09; 配置目录Ctrl 鼠标方法缩小字体 配置目录 IDEA 在使用的过程中会在 C 盘的用户目录下写入相关配置&#xff0c;目录如下&#xff1a; "C:\Users\个人用户名\AppData\Local\JetBrains" "C:\Users\个人用户名\AppDa…

在线制作假期承诺书,电子手写签名确认,一键导出打印。

假期将至&#xff0c;为积极落实安全管理规定&#xff0c;单位通常需要下发安全承诺书进行签字确认。 易查分可以实现网上下发安全承诺书通知&#xff0c;让查询者进行签名确认&#xff0c;还可以生成PDF&#xff0c;方便打印一人一张的纸质版承诺书&#xff0c;本次就来介绍如…

C#编程-实现函数重载

考虑一个示例&#xff1a;您必须编写一个程序来实现计算器的功能。计算器执行各种运算&#xff0c;例如数字的加、减及乘等。可以对任何类型的数据执行这些运算。这是否意味着您必须定义单独的函数名&#xff08;如addInteger、addFloat和addDoublie&#xff09;对每种此类数字…

扫码支付是怎么工作的?

扫码支付是怎么工作的&#xff1f; 本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 过去的几十年&#xff0c;支付技术发生了很大的改变。下图给我们显示了 POS 终端的进化。从一开始的纸钞收银机&#xff0c;到刷卡机&#xff0c;再到…

Python 教程 02:Python 编程环境的搭建与 IDE 的选择

目录 一、搭建 Python 环境 1.1 Python 官网 1.2 下载 Python 1.2.1 选择版本 1.2.2 选择平台 1.2.3 下载安装文件&#xff08;Windows & macOS&#xff09; 1.3 安装环境 1.3.1 Windows 平台 1.3.2 macOS 平台 1.3.3 Linux 平台 1.4 验证安装是否成功 二、选择…

OpenHarmony应用构建工具Hvigor的构建流程

前言 OpenHarmony 应用和服务使用 Hvigor 作为工程的构建工具。本篇文章将介绍 Hvigor 的构建流程&#xff0c;通过修改脚本配置使 Hvigor 执行自定义任务。 Hvigor 的构建流程 加载命令行参数和环境变量&#xff1b;初始化项目结构&#xff0c;创建 Project 和 Module 实例…

计算机网络-VLAN原理与配置

之前我们学习了以太网的基础知识&#xff0c;了解了网络交换设备的发展&#xff0c;交换机的工作原理&#xff0c;广播域和冲突域。 一、概述 还简单了解了以太网的CSMA/CD通讯机制&#xff0c;以太网是建立在CSMA/CD (Carrier Sense Multiple Access/Collision Detection&…

C++ 学习笔记之运算符重载+案例

目录 一、C 运算符重载 二、定义一个成员函数或全局函数 三、计算时间 1.计算时间差 2.时间加减 四、一个运算符重载实例 一、C 运算符重载 是一种特性&#xff0c;它允许程序员重新定义已有的运算符的行为&#xff0c;以适应自定义类型的操作。通过运算符重载&#xff0…