AcWing 802. 区间和(离散化算法,python)

本篇博客详细讲解一下离散化知识点,通过讲解和详细列题带大家掌握离散化。

题目:

原题链接:https://www.acwing.com/problem/content/description/804/

假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。

输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。

输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。

数据范围
− 1 0 9 ≤ x ≤ 1 0 9 -10^9≤x≤10^9 109x109,
1 ≤ n , m ≤ 1 0 5 1≤n,m≤10^5 1n,m105,
− 1 0 9 ≤ l ≤ r ≤ 1 0 9 −10^9≤l≤r≤10^9 109lr109,
− 10000 ≤ c ≤ 10000 −10000≤c≤10000 10000c10000

输入样例:

3 3
1 2
3 6
7 5
1 3
4 6
7 8

输出样例:

8
0
5

什么是离散化?

   本题猛的一看似乎就是一道前缀和的模板题,但需要注意到这里所谓的“坐标”的范围较大,范围在 − 1 0 9 ≤ x ≤ 1 0 9 -10^9≤x≤10^9 109x109,为了存下被修改的点的数据,如果将它们的坐标作为数组的下标就需要开一个 2 ∗ 1 0 9 2*10^9 2109大小的数组,肯定会爆内存,况且这里的坐标还有负值,不方便进行存储。

   所以要提出一个新的能方便快捷存数据的算法——离散化

   离散化的内存优化思路是只存储那些被用到的点(在这里指的是“被加了值的点”以及“要查询区间的两个端点”),然后利用一些较小的值来代替它们的坐标进行索引,并最终保持它们的相对位置。

   举个例子:对于“被用到的点”只有四个:1、11、886、320001,如果用传统的存储方式要开1~320001个连续的存储空间,但其实没必要,因为会浪费掉了很多没有用到的空间。其实它们的相对位置可以分别用1(1)、2(11)、3(886)、4(320001)来替代,进而只需要开1~4个连续的存储空间并且全部用上;反观此题的数据量,操作次数决定要存点的个数,n、m均小于等于 1 0 5 10^5 105,所以“被用到的点”最多为 n + 2 m = 3 ∗ 1 0 5 n + 2m =3 *10^5 n+2m=3105个 ,也即内存从 2 ∗ 1 0 9 2 * 10^9 2109优化到了 3 ∗ 1 0 5 3 * 10^5 3105,整整少了4个数量级!

   因此,点的存储位置变为连续,但其表示的值却为离散,故而称其被离散化。

如何离散化?(题解)

   为了能够将较大的坐标点及其该坐标点上的数值存储下来,就需要使用两个映射:

  1. total_num(数组):用来存放题目中用到的坐标点,也就是题中的x, l, r,初始值为空数组。total_num数组表示坐标到相对位置的映射:先将题目中输入样例给出的坐标点全都放入(append)total_num数组后,进行一遍排序和去重,这样就必能保证小的坐标位置在前,大坐标在后,此时下标就是它们新的“相对位置”。
  2. a(数组):用来存放离散化后的坐标的值的变化,初始范围为 3 ∗ 1 0 5 + 10 3 * 10^5 + 10 3105+10 (n + 2m 最大为 3 ∗ 1 0 5 3 * 10^5 3105)。表示相对位置到坐标点上的数值的映射:拿到坐标点的相对位置new_x后,a[new_x] += c就存下了坐标点的数据了。

   这里还需要定义add_num数组用来存放整数(x, c),定义query_num数组,用来存放询问的区间(l, r)

   再定义a的前缀和数组s,预处理完后利用s[r] - s[l - 1]就能得到 [l,r] 区间和了。

   下面来详细讲解一下各数组的作用和具体实现方法:

   首先初始化各个数组,其中a数组和s数组的长度为 3 ∗ 1 0 5 + 10 3 * 10^5 + 10 3105+10,值为0,其余数组初始为空。

   total_num数组为何除了要存被改动点的坐标x还要存储查询区间的两端点l和r呢?

   主要是因为后续要通过s[r] - s[l - 1]来获取到区间和,而必须将它们在坐标轴上的情况也存下来才能知道这个区间的情况,因而它也算作“被用到的点”。

   那么被改动点(x, c)和查询端点(l, r)分别还要再放到add_num和query_num里方便处理。

   具体的存储情况还可以下图为例:
在这里插入图片描述
   这里还有一个难点就是如何进行离散化?也就是如何把total_num数组映射到a数组上?这里需要借用二分来进行插入操作,二分的初始左端点 l 为0,右端点 r 为total_num数组的长度减一,mid = (l+r) // 2,传入参数是x(这里的x是toal_num里的数值,需要对total_num进行遍历并挨个把total_num中的值映射到a数组中),只要total_num[mid] <= x,那么r = mid 否则 l = mid + 1,最后返回值是 l + 1

   为什么返回的是 l + 1 呢?因为a数组和s数组的下标是从1开始的(下标从1开始是方便处理前缀和),所以这里需要进行+1操作。

   下面给出详细代码和注释:

# 读取输入的n和m,分别表示添加操作的数量和查询操作的数量  
n, m = map(int, input().split())  
N = 300010  
a = [0] * N  
s = [0] * N  
# 用于存储添加操作的列表,每个元素是一个元组,包含要添加的数值x和对应的增量c  
add_num = []  
# 用于存储查询操作的列表,每个元素是一个元组,包含查询的区间左端点l和右端点r  
query_num = []  
# 用于存储所有出现过的坐标
total_num = []  # 读取n个添加操作  
for i in range(n):  x, c = map(int, input().split())  add_num.append((x, c))  total_num.append(x)  # 将x添加到total_num中  # 读取m个查询操作  
for i in range(m):  l, r = map(int, input().split())  query_num.append((l, r))  total_num.append(l)  # 将l添加到total_num中  total_num.append(r)  # 将r添加到total_num中  # 对total_num进行排序并去重,得到所有唯一出现过的数值  
total_num = list(set(sorted(total_num)))  # 定义一个查找函数,用于在total_num中找到数值x映射到a的位置(索引从1开始)  
def find(x):  l = 0  r = len(total_num) - 1  while l < r:  mid = (l + r) // 2  if total_num[mid] >= x:  r = mid  else:  l = mid + 1  return l + 1# 对每个添加操作进行处理,将增量c添加到对应的位置  
for x, c in add_num:  new_x = find(x)  # 找到total_num中x映射到a的位置a[new_x] += c    # 将增量c添加到a数组的对应位置  # 计算前缀和数组s  
for i in range(1, N):  s[i] = s[i - 1] + a[i]  # 前缀和公式# 对每个查询操作进行处理,计算并输出区间和  
for l, r in query_num:  xl = find(l)  xr = find(r)  print(s[xr] - s[xl - 1])

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

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

相关文章

记一次pyc逆向

.py文件   源代码文件。   这是开发者编写的 Python 源代码文件&#xff0c;包含了可执行的 Python 代码。 .pyc文件   字节码文件。   Python 源文件&#xff08;.py&#xff09;在执行时会被编译为字节码&#xff0c;并存储在 __pycache__ 目录下&#xff0c;文件名通…

PHP变量(第④篇)

本栏目教学是php零基础到精通&#xff0c;如果你还没有安装php开发工具请查看下方链接&#xff1a; Vscode、小皮面板安装-CSDN博客 今天来讲一讲php中的变量&#xff0c;变量是用于存储信息的"容器"&#xff0c;这些数据可以在程序执行期间被修改&#xff08;即其…

解决Nginx出现“Too many open files”的问题

解决Nginx出现“Too many open files”的问题 在那个不经意的瞬间&#xff0c;我感到一阵莫名的恍惚。同事突然提出要看我的手机&#xff0c;她的目光落在了我那泛黄的手机壳上。出乎意料地&#xff0c;她开始细心地擦拭&#xff0c;从内到外&#xff0c;动作轻柔而专注。那一刻…

Linux——磁盘分区、挂载

Linux 分区 原理介绍 原理图如下 当我们在/home目录下新建一个文件a.txt时&#xff0c;该文件实际上是存放在硬盘B的分区1中的&#xff0c;这就是图里说的&#xff0c;当进入某个目录&#xff0c;可以进入到该目录下挂载的分区里的意思 硬盘说明 应用实例&#xff1a;挂载一个…

【Flask】Flask数据库

【Flask】Flask数据库 1.概述2.使用Flask-SQLAlchemy管理数据库3.定义模型4.关系5.数据库操作创建表插入行修改行删除行查询行 1.概述 大多数的数据库引擎都有对应的 Python 包&#xff0c;包括开源包和商业包。Flask 并不限制你使用何种类型的数据库包&#xff0c;因此可以根…

PhotoMaker部署文档

一、介绍 PhotoMaker&#xff1a;一种高效的、个性化的文本转图像生成方法&#xff0c;能通过堆叠 ID 嵌入自定义逼真的人类照片。相当于把一张人的照片特征提取出来&#xff0c;然后可以生成你想要的不同风格照片&#xff0c;如写真等等。 主要特点&#xff1a; 在几秒钟内…

前端登录页面验证码

首先&#xff0c;在el-form-item里有两个div&#xff0c;各占一半&#xff0c;左边填验证码&#xff0c;右边生成验证码 <el-form-item prop"code"><div style"display: flex " prop"code"><el-input placeholder"请输入验证…

小赢卡贷公益行:乡村振兴与多元公益并进

在金融科技的浪潮中&#xff0c;小赢卡贷不仅以其创新的金融产品和服务赢得了市场的广泛认可&#xff0c;更以其背后的公益之心&#xff0c;积极履行社会责任&#xff0c;传递着温暖与希望。小赢公益基金会&#xff0c;作为小赢卡贷社会责任的延伸&#xff0c;主要聚焦于乡村振…

Hi3061M开发板——系统时钟频率

这里写目录标题 前言MCU时钟介绍PLLCRG_ConfigPLL时钟配置另附完整系统时钟结构图 前言 Hi3061M使用过程中&#xff0c;AD和APT输出&#xff0c;都需要考虑到时钟频率&#xff0c;特别是APT&#xff0c;关系到PWM的输出频率。于是就研究了下相关的时钟。 MCU时钟介绍 MCU共有…

unix中如何申请进程调度的优先级

一、前言 unix系统中&#xff0c;进程的调度是由内核决定的。在一个系统中&#xff0c;进程的优先级越高&#xff0c;表示其在一定时间中占用cpu的时间越久。本文将介绍unix系统如何修改以及获取进程的优先级。 二、nice值 nice值是unix系统中用于表征进程优先级的一个参数。…

ssh -T git@github.com 出现异常

上传代码到github 私有仓库 步骤 1. 生成 SSH Key&#xff08;如果没有&#xff09; 打开终端并运行&#xff1a; bash 复制 ssh-keygen -t ed25519 -C "your_emailexample.com"按提示保存密钥文件和设置密码短语&#xff08;可选&#xff09;。默认位置是 ~/.…

recyclerView(kotlin)

recyclerView的优点 使用viewHolderRecycledViewPool的方式复用资源&#xff0c;提高性能利用LayoutManager&#xff0c;可根据不同需求使用不同的布局&#xff0c;且可以方便使用对应布局提供的方法&#xff0c;如快速定位item等。RecyclerView 提供了一个 ItemAnimator 接口…

计算机毕业设计Django+Vue.js豆瓣图书推荐系统 图书评论情感分析 豆瓣图书可视化大屏 豆瓣图书爬虫 数据分析 图书大数据 大数据毕业设计 机器学习

《DjangoVue.js豆瓣图书推荐系统》开题报告 一、研究背景与意义 1. 研究背景 随着数字化时代的来临&#xff0c;图书资源日益丰富&#xff0c;用户面临着信息过载的问题。如何在海量图书中快速找到符合个人兴趣和需求的书籍成为了亟待解决的问题。传统的图书检索方式往往基于…

OmniDrive 论文学习

OmniDrive: A Holistic LLM-Agent Framework for Autonomous Driving with 3D Perception, Reasoning and Planning 解决了什么问题&#xff1f;相关工作端到端自动驾驶多模态语言模型&#xff08;MLLMs&#xff09;Drive LLM-Agents and BenchmarksDrive LLM-Agents基准测试 提…

柔性作业车间调度(FJSP)

1.1 调度问题的研究背景 生产调度是指针对一项可分解的工作(如产品制造),在尽可能满足工艺路线、资源情况、交货期等约束条件的前提下,通过下达生产指令,安排其组成部分(操作)所使用的资源、加工时间及加工的先后顺序,以获得产品制造时间或成本最优化的一项工作。 一般研究车间…

MySQL 日志 - Binlog

文章目录 binlog 的格式mysqbinlog 工具SHOW binlog events;binlog 和 redo log 对比 https://dev.mysql.com/doc/refman/8.4/en/binary-log.html binlog 全称 BinaryLog&#xff0c;是 MySQL 数据库中用于记录所有更改数据库状态的事件的日志文件。它主要用于以下几个目的&am…

【hot100-java】二叉树中的最大路径和

二叉树篇 easy. /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

考试宝 逆向 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我…

Ping32引领数据防泄漏新潮流:智能、高效、安全

在当今数字化迅猛发展的时代&#xff0c;企业面临着日益严峻的数据安全挑战。数据泄漏事件频发&#xff0c;不仅损害企业声誉&#xff0c;还可能导致巨额的经济损失。为此&#xff0c;Ping32以其创新的数据防泄漏解决方案&#xff0c;正在引领行业新潮流。其技术特点可概括为“…

集师知识付费小程序:打造培训机构在线教育的金字招牌 集师知识付费系统 集师知识付费小程序 集师知识服务系统 集师线上培训系统 集师线上卖课小程序

在数字化浪潮的推动下&#xff0c;在线教育已成为教育领域的热门话题。而在众多在线教育平台中&#xff0c;集师知识付费小程序凭借其独特的定位和创新的模式&#xff0c;成功为培训机构打造了一张闪亮的在线教育金字招牌。 集师知识付费小程序&#xff0c;是一个集课程展示、…