离散化笔记

文章目录

  • 离散化的适用条件
  • 离散化的意思
  • AcWing 802. 区间和
    • CODE
    • CODE2



离散化的适用条件

  • 离散化用于区间求和问题
  • 对于数域极大,而数的量很少的情况下

离散化的意思

  • 背景:对于一个极大数域上的零星几个数进行操作后,求某段区间内的和
    • 其实意思就是大数域映射到一个小数域内。比如我的操作是:第 30 30 30 位加 10 10 10,第 2000 2000 2000 位加 50 50 50,第 1 0 6 10^6 106 位加 100 100 100,映射后我的操作就是a[1] += 10a[2] += 50a[3] += 100,也就是说,我们将零散的数域变得紧凑。

    • 我们如何做到将序列号变紧密而且不重复呢?

      • 首先,我们将需要转化的序列号存在一个数组a[]内,序列号就是我们在大数域内进行操作时的序列号(操作包括对某一号元素进行改值,或者是求区间之和的时候区间的左右端点。这些都是大数域上的序列号)
      • 之后,我们将这些序列号进行排序,然后去掉重复的号。
        • 这步操作的意思是,每个大数域上的序列号在小数域上只能有一个编号与其对应,所以需要去除重复的大序列号
      • 我们用数组a[]的下标作为小数域上与大数域相对应的编号
      • 所以说我们其实是通过一个数组来将序列号缩小的
    • 最后我们使用前缀和算法快速求得多个询问的区间和即可


AcWing 802. 区间和

题目链接:AcWing 802. 区间和

区间和

CODE

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int, int> pii; 	 // 定义一个pair类型的别名PII,用于存储一对整数

int n, m; 	 // n和 m 分别表示插入操作和查询操作的数量
const int N = 300010; 	// 定义一个常量N,作为数组的大小
int a[N], s[N]; 	 	// a数组用于存储每个位置的数值,s数组用于存储前缀和

vector<int> alls; 	 		// alls向量用于存储所有出现过的数
vector<pii> add, query;		// add向量用于存储所有的插入操作,query向量用于存储所有的查询操作

int l, r;  	// l和r用于存储查询操作的左右边界
int x, c;  	// x和c用于存储插入操作的数和次数

int find(int x) 	 // find函数用于在alls向量中找到x的位置
{
    int l = 0, r = alls.size() - 1;
    
    while(l < r){
        int mid = (l + r) >> 1;
        if(alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    
    return r + 1;
}

int main()
{
    cin >> n >> m;  	// 输入插入操作和查询操作的数量
    while (n -- ){
        cin >> x >> c;
        add.push_back({x, c});
        
        alls.push_back(x); 	 // 将x加入到alls向量中
    }
    
    while (m -- ){
        cin >> l >> r;
        query.push_back({l, r});
        
        alls.push_back(l);  	// 将l和r加入到alls向量中
        alls.push_back(r);
    }
    
    // 去重
    sort(alls.begin(), alls.end());  	// 对alls向量进行排序
    alls.erase(unique(alls.begin(), alls.end()), alls.end());  // 删除alls向量中的重复元素
    
    // 找加入元素的位置并初始化加入数组
    for(auto item : add){
        int x = find(item.first);
        a[x] += item.second;
    }
    
    // 前缀和
    for(int i = 1; i <= alls.size(); ++i) s[i] += s[i - 1] + a[i];
    
    // 询问
    for(auto item : query){
        l = find(item.first), r = find(item.second);
        printf("%d\n", s[r] - s[l - 1]);
    }
}

  • 其实由上述过程和代码我们可以发现,我们用数组来缩小数域的思路与哈希表不谋而合,所以说我们可以用哈希表来存我们的操作数的序列号,这样的话能将二分的 O ( l o g n ) O(logn) O(logn) 优化到哈希表的 O ( 1 ) O(1) O(1)

  • 但是我们不能用手写的简易哈希表(单指开放寻址和拉链法,能优化成map当我没说)
    因为开放寻址法中,我们需要对对所有数进行取模操作,而模量N是较小的,而数据的编号很大,所以就可能出现我们映射的范围出现问题,例如一个区间[l, r],我们用的模量N满足: l < N < r l < N < r l<N<r,这个时候我们有个尴尬的问题,我们的l映射之后比r大,那么再对这个区间求和时就回出现错误

  • 这个时候就需要我们伟大的 S T L STL STL 出场了,unordered_map很好的解决了我们的问题
    map的实现

    map
    不得不说,C++真的很牛逼啊,那老头真吊

CODE2

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

typedef pair<int, int> pii;

int n, m;
const int N = 300010;
int a[N], s[N];
vector<int> alls;
vector<pii> add, query;
int l, r;
int x, c;

int find(int x){
    int l = 0, r = alls.size() - 1;
    
    while(l < r){
        int mid = (l + r) >> 1;
        if(alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    
    return r + 1;
}



int main()
{
    cin >> n >> m;
    while (n -- ){
        cin >> x >> c;
        add.push_back({x, c});
        
        alls.push_back(x);
    }
    
    while (m -- ){
        cin >> l >> r;
        query.push_back({l, r});
        
        alls.push_back(l);
        alls.push_back(r);
    }
    
    // 去重
    sort(alls.begin(), alls.end());
    alls.erase(unique(alls.begin(), alls.end()), alls.end());
    
    unordered_map<int, int> indx;
    for(int i = 1; i <= alls.size(); ++i) indx[alls[i - 1]] = i;
    
    // 找加入元素的位置并初始化加入数组
    for(auto item : add){
        int x = indx[item.first];
        a[x] += item.second;
    }
    
    // 前缀和
    for(int i = 1; i <= alls.size(); ++i) s[i] += s[i - 1] + a[i];
    
    // 询问
    for(auto item : query){
        l = indx[item.first], r = indx[item.second];
        printf("%d\n", s[r] - s[l - 1]);
    }
}

这个代码是我从评论区抄的,位置:https://www.acwing.com/solution/content/13511/,往下翻评论区有个哈希表代码

但是我怎么都看不懂他哈希表的赋值操作

for(int i = 1; i <= alls.size(); ++i) indx[alls[i - 1]] = i;

艹!!!!!!!!!为什么!!!!!!!!!
问bing,他跟我说因为是我在之前对alls[]数组排序去重了,所以区间[l, r]肯定不会映射出错,r映射完肯定比l大,但是我问他是因为键有序所以导致哈希表映射后相对顺序不变吗,它又说不是,然后就是一堆我看不懂的谜语,一直复读复读复读,啊啊啊啊啊啊啊好痛苦啊啊啊啊啊啊

我把对键的赋值改了,不赋为i,但是又 W A WA WA,真的很烦啊,想不出来为什么,等我以后深入一下 S T L STL STL 再说吧 <_>,蒟蒻是这样的。

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

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

相关文章

【机器学习 | 可视化系列】可视化系列 之 决策树可视化

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

沈阳师范大学期末考试复习pta循环数组函数指针经典编程题汇总+代码分析

前言&#xff1a;临近期末&#xff0c;接下来给大家分享一些经典的编程题&#xff0c;方便大家复习。不一定难&#xff0c;但都是入门的好题&#xff0c;尽可能的吃透彻。因为据说期末考试的题很多来自pta上面的原题。 对于一些语言我是用c来写的&#xff0c;不妨碍理解&#…

express+multer实现简单的文件上传功能

expressmulter实现简单的文件上传功能 1.安装multer和uuid依赖 cnpm install -S uuid multer2.添加multer的配置文件 在config文件夹下添加uploa.js文件&#xff0c;内容如下&#xff1a; // 引入multer const multer require(multer) // uuid : 用于生成不重复的由英文组…

Java EE 多线程

文章目录 1. 认识线程1.1 什么是进程1.2 什么是线程1.2.1. 线程是怎么做到的呢&#xff1f;1.2.2. 进程和线程的关系 1.3 多线程编程1.3.1. 第一个多线程程序1.3.2. 使用 jconsole 命令查看线程1.3.3. 实现 Runnable 接口&#xff0c;重写 run1.3.4. 继承 Thread 重写 run&…

存款买房(Python)

&#x1f4d1;前言 本文主要是【Python】——Python存款买房问题的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

【数据结构】——解决topk问题

前言&#xff1a;我们前面已经学习了小堆并且也实现了小堆&#xff0c;那么我们如果要从多个数据里选出最大的几个数据该怎么办呢&#xff0c;这节课我们就来解决这个问题。我们就用建小堆的方法来解决。 首先我们来看到这个方法的时间复杂度&#xff0c;我们先取前k个数据建立…

LLM三阶段训练代码汇总

在进行大模型的阶段训练时,从头编写代码有点浪费时间。为了更高效地实现这一目标,我们可以利用GitHub上已有的现成代码。下面对现成的代码库进行总结。 欢迎关注公众号 1. LLaMA-Factory LLaMA Factory: 轻松的大模型训练与评估 https://github.com/hiyouga/LLaMA-Factory …

c++[string实现、反思]

我的码云 我的string码云 分析总结 1.项目结构 所有的类和函数需要在namespace中实现&#xff0c;要和string高度对应 private:char* _str;//字符串size_t _size;//有效长度size_t _capacity;//总空间&#xff0c;包括\0const static size_t npos-1;2.定义变量 <1> 所…

前端开发_HTML

简介 CSS用于美化内容 HTML用于摆放内容 可以理解为HTML是基础&#xff0c;CSS是工具 HTML定义 HTML 超文本标记语言——HyperText Markup Language 超文本——链接 标记——标签&#xff0c;即带尖括号的文本 标签语法 双标签 开始标签&#xff1a; <xxx> 即尖…

WARNING: Access control is not enabled for the database.

MongoDB shell version v3.4.24 WARNING: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted. 1)未启用访问控制 2)读写访问不受限制 D:\MongoDB\Server\3.4\bin>mongo MongoDB shell version v3.4.24 c…

操作系统 day14(进程同步、进程互斥、互斥的代码实现、互斥的硬件实现、互斥锁)

进程同步 概念 进程的异步性体现在&#xff0c;例如&#xff1a;当有I/O操作时&#xff0c;进程需要等待I/O操作&#xff0c;而每个I/O操作又是不同的&#xff0c;所以进程没有一个固定的顺序&#xff0c;固定的时间来执行&#xff0c;而这体现了进程的异步性。 进程互斥 …

广域网加速技术

摘要&#xff1a; 随着企业数字化转型快速发展&#xff0c;越来越多企业将IT系统、应用和服务部署到云上&#xff0c;以实现更高效、灵活的管理和使用。这就对广域网提出了更高的要求&#xff0c;而广域网线路往往存在带宽费用昂贵、服务质量不可靠等问题。为了改善用户体验&am…

RabbitMQ消息的应答

消息的应答机制 消费者完成一个任务可能需要一段时间&#xff0c;如果其中一个消费者处理一个长的任务并仅只完成了部分突然它挂掉了&#xff0c;会发生什么情况。RabbitMQ 一旦向消费者传递了一条消息&#xff0c;便立即将该消息标记为删除。在这种情况下&#xff0c;突然有个…

【MySQL】常用内置函数:数值函数 / 字符串函数 / 日期函数 / 其他函数

文章目录 数值函数round()&#xff1a;四舍五入ceiling()&#xff1a;上限函数floor()&#xff1a;地板函数abs()&#xff1a;计算绝对值rand()&#xff1a;生成0-1的随机浮点数 字符串函数length()&#xff1a;获取字符串中的字符数upper() / lower()&#xff1a;将字符串转化…

基于springboot+vue的在线考试系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

水果编曲软件FL Studio21最新中文版本2023年最新FL 21中文版如何快速入门教程

水果编曲软件FL Studio介绍 各位&#xff0c;大家晚上好&#xff0c;今天给大家带来最新最新2023水果编曲软件FL Studio 21中文版下载安装激活图文教程。我们一起先了解一些FL Studio 。FL Studio21是目前流行广泛使用人数最多音乐编曲宿主制作DAW软件&#xff0c;这款软件相信…

git stash save untracked not staged

git stash save untracked not staged 如图 解决方案&#xff1a; git stash save "tag标记信息" --include-untracked或者&#xff1a; git stash save -u "tag标记信息" git stash clear清空本地暂存代码_zhangphil的博客-CSDN博客文章浏览阅读486次。…

QDoubleSpinBox的使用示例

QDoubleSpinBox即可以做为数值型输入框使用&#xff0c;也可以使用只读型数据显示框&#xff0c;在作为输入框使用时比QLineEdit有以下几个方面的优势 1.可以设置范围&#xff0c;并且范围精确&#xff0c; 2.输入数据精确&#xff0c;自动屏幕非数值以外的字符。 3.设置步长后…

LeetCode(40)同构字符串【哈希表】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 同构字符串 1.题目 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0…

java开发需要用到的软件,必备软件工具一览

java开发需要用到的软件&#xff0c;必备软件工具一览 如果你对Java编程感兴趣或已经是一名Java开发者&#xff0c;你需要一些必备的软件工具来提高你的生产力和简化开发过程。在本文中&#xff0c;我们将探讨Java开发所需的关键软件工具&#xff0c;并通过具体示例来解释它们的…