离散化——Acwing.802区间和

离散化

定义

离散化可以简单理解为将连续的数值或数据转换为离散的、有限个不同的值或类别。离散化就是将一个可能具有无限多个取值或在一个较大范围内连续取值的变量,通过某种规则或方法,划分成若干个离散的区间或类别,并将原始数据映射到这些离散的类别中。

主要目的通常是为了简化数据处理、降低数据维度、提高计算效率或适应特定的算法和模型要求。离散化可以去除一些不太重要的细节信息,突出数据的主要特征和模式。

运用情况

当数据范围很大,但实际涉及到的不同值相对较少时,通过离散化可以用较小的索引或标记来代表原来的数值,从而节省空间和提高处理效率。

例如,有一组数值可能非常大(比如从 1 到 1000000),但实际上只有少数几种不同的值频繁出现,通过离散化可以将这些值映射到一个较小的范围内(比如 1 到 10)。

离散化的一个常见做法是先对原始数据进行排序,然后为每个不同的值分配一个唯一的编号或索引。这样在后续的处理中就可以用这些编号来代替具体的数值进行操作。

离散化在一些算法中,如一些基于区间或计数的问题中经常被用到,可以使问题的处理更加简洁和高效。

注意事项

  1. 要确保离散化后的数据能准确反映原始数据的关键特征和关系,不能丢失重要信息。
  2. 注意边界情况的处理,避免出现遗漏或错误分类。
  3. 对于不同的应用场景,选择合适的离散化方法,考虑数据分布特点和后续算法的需求。

离散方法

  1. 等宽离散化:将数据的取值范围划分为若干个等宽的区间,每个区间对应一个离散值。
  2. 等频离散化:将数据划分为若干个区间,使得每个区间内的数据数量大致相等。
  3. 基于聚类的离散化:利用聚类算法将数据聚成若干类,然后将这些类作为离散化后的类别。
  4. 基于特定规则的离散化:根据具体问题和业务需求,人为设定一些规则来进行离散化,比如根据某个阈值进行划分。
  5. 基于决策树的离散化:通过构建决策树,根据节点分裂的情况来确定离散化的划分点。

解题思路

  1. 分析问题:确定是否适合使用离散化,以及离散化的目的是什么。
  2. 选择方法:根据数据特点和问题需求选择合适的离散化方法,如等宽、等频等。
  3. 处理数据:按照选定的方法对数据进行离散化操作,建立映射关系。
  4. 验证效果:检查离散化后的数据在后续处理或分析中是否达到预期效果,必要时进行调整。
  5. 结合算法:考虑离散化后如何与具体的算法或模型相结合,使其更好地发挥作用。

例如,在处理一些区间相关的问题时,可能先对区间的端点进行离散化,然后根据离散化后的索引进行计算和处理;或者在数据量很大但实际不同值有限的情况下,通过离散化来提高存储和计算效率。同时,在解题过程中要不断思考如何优化离散化的过程以及更好地利用离散化后的结果。

Acwing.802区间和

题目描述

802. 区间和 - AcWing题库

运行代码

#include<bits/stdc++.h>  
using namespace std;  
typedef pair<int, int> PII;  
const int N = 300010;  
PII add[N];  
PII query[N];  
int a[N], s[N];  
vector<int> alls;  
int find(int x) {  
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;  
}  

int main() {  
    int n, m;  
    cin >> n >> m;  
    // 读取修改操作并存储到alls中  
    for (int i = 0; i < n; i++) {  
        cin >> add[i].first >> add[i].second;  
        alls.push_back(add[i].first);  
    }  
    // 读取查询操作并存储到alls中  
    for (int i = 0; i < m; i++) {  
        cin >> query[i].first >> query[i].second;  
        alls.push_back(query[i].first);  
        alls.push_back(query[i].second);  
    }  
    // 离散化  
    sort(alls.begin(), alls.end());  
    alls.erase(unique(alls.begin(), alls.end()), alls.end());  
    // 根据离散化后的位置更新a数组  
    for (int i = 0; i < n; i++) {  
        int pos = find(add[i].first);  
        a[pos] += add[i].second;  
    }  
    // 计算前缀和  
    for (int i = 1; i <= alls.size(); i++) {  
        s[i] = s[i - 1] + a[i];  
    }  
    // 处理查询  
    for (int i = 0; i < m; i++) {  
        int l = find(query[i].first);  
        int r = find(query[i].second);  
        cout << s[r] - s[l - 1] << endl;  
    }  
    return 0;  
}

代码思路

  1. 读取输入
    • 读取修改操作的个数 n 和查询操作的个数 m
    • 读取每个修改操作,包括修改的位置 x 和增加的值 c,并将位置 x 存储在 add 数组中。
    • 读取每个查询操作,包括查询的左边界 l 和右边界 r,并将它们存储在 query 数组中。
  2. 离散化:将所有修改和查询中涉及到的位置(即 add 和 query 数组中的 xl 和 r)存储到 alls 向量中。对 alls 向量进行排序,并使用 unique 函数去除重复元素,实现离散化。
  3. 更新数组:遍历 add 数组,对于每个修改操作,使用 find 函数找到离散化后的位置 pos,并更新 a[pos] 数组的值。
  4. 计算前缀和:遍历离散化后的位置数组 alls(从索引 1 开始,因为索引 0 不代表任何位置),计算 a 数组的前缀和,并将结果存储在 s 数组中。
  5. 处理查询
    • 遍历 query 数组,对于每个查询操作,使用 find 函数找到离散化后的左边界 l 和右边界 r 的位置。
    • 输出区间和 s[r] - s[l - 1],其中 s[r] 是右边界的前缀和,s[l - 1] 是左边界左边一个位置的前缀和(用于排除左边界本身)。
  6. 输出结果:对于每个查询操作,输出计算得到的区间和。

这个代码的时间复杂度主要由离散化、更新数组、计算前缀和以及处理查询四部分组成。其中,离散化和计算前缀和的时间复杂度都是 O(n log n),其中 n 是修改和查询操作的总数(因为 alls 的大小可能达到这个数量级)。更新数组和处理查询的时间复杂度都是 O(n),所以整体的时间复杂度是 O(n log n)。

改进思路

  1. 减少alls数组中的冗余元素:在将位置加入alls数组时,如果两个修改或查询操作的位置相同,我们只需要存储一个。这可以通过在加入新位置之前检查alls数组的末尾元素是否与新位置相同来实现。

  2. 使用std::vectorback_inserter:在将位置加入alls数组时,使用std::back_inserter可以避免显式地调用push_back,这可能会稍微提高性能。

  3. 使用std::lower_bound的返回值直接作为索引:在find函数中,我们可以直接使用std::lower_bound返回的迭代器减去alls.begin()得到离散化后的索引,而不是将其转换为整数。

改进代码(AI)

#include<bits/stdc++.h>  
using namespace std;  
typedef pair<int, int> PII;  
const int N = 300010;  
  
PII add[N];  
PII query[N];  
int a[N], s[N];  
vector<int> alls;  
  
int find(int x) {  
    return lower_bound(alls.begin(), alls.end(), x) - alls.begin() + 1;  
}  
  
int main() {  
    int n, m;  
    cin >> n >> m;  
  
    // 读取修改操作  
    for (int i = 0; i < n; i++) {  
        cin >> add[i].first >> add[i].second;  
        if (alls.empty() || alls.back() != add[i].first) alls.push_back(add[i].first);  
    }  
  
    // 读取查询操作  
    for (int i = 0; i < m; i++) {  
        cin >> query[i].first >> query[i].second;  
        if (alls.empty() || alls.back() != query[i].first) alls.push_back(query[i].first);  
        if (alls.empty() || alls.back() != query[i].second) alls.push_back(query[i].second);  
    }  
  
    // 离散化  
    sort(alls.begin(), alls.end());  
    alls.erase(unique(alls.begin(), alls.end()), alls.end());  
  
    // 根据离散化后的位置更新a数组  
    for (int i = 0; i < n; i++) {  
        int pos = find(add[i].first);  
        a[pos] += add[i].second;  
    }  
  
    // 计算前缀和  
    for (int i = 1; i <= alls.size(); i++) {  
        s[i] = s[i - 1] + a[i];  
    }  
  
    // 处理查询  
    for (int i = 0; i < m; i++) {  
        int l = find(query[i].first);  
        int r = find(query[i].second);  
        cout << s[r] - s[l - 1] << endl;  
    }  
  
    return 0;  
}

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

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

相关文章

【Go】用 Go 原生以及 Gorm 读取 SQLCipher 加密数据库

本文档主要描述通过 https://github.com/mutecomm/go-sqlcipher 生成和读取 SQLCipher 加密数据库以及其中踩的一些坑 用 go 去生成读取 SQLCipher 数据库用 gorm 去读取 SQLCipher 数据库在生成后分别用 DBeaver、db browser 和 sqlcipher 读取 SQLCipher 数据库&#xff0c;…

基于jeecgboot-vue3的Flowable流程-流程处理(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 对应VForm3&#xff0c;原先的后端解析也要做调整 1、获取历史任务的表单信息 // 获取历史任务节点表单数据值List<HistoricVariableInstance> listHistoricVariableInstance his…

Python第二语言(十二、SQL入门和实战)

目录 1. Python中使用MySQL 1.1 pymysql第三方库使用MySQL 1.2 连接MySQL 1.3 操作数据库&#xff0c;创建表 1.4 执行查询数据库语句 2. python中MySQL的插入语句 2.1 commit提交 2.2 自动提交 3. pymysql案例 3.1 数据内容 3.2 DDL定义 3.3 实现步骤 3.4 文件操…

最小生成树kruskal算法详解

kruskal算法的思想简单来说就是&#xff1a;每次选择图中最小边权的边&#xff0c;如果边两端的顶点不在相同的连通块中&#xff0c;就把这条边加入到最小生成树中。 具体实现如下&#xff1a; 首先是边的定义&#xff0c;需要判断边的两个端点是否在不同的连通块中&#xff…

Vue前端ffmpeg压缩视频再上传(全网唯一公开真正实现)

1.Vue项目中安装插件ffmpeg 1.1 插件版本依赖配置 两个插件的版本 "ffmpeg/core": "^0.10.0", "ffmpeg/ffmpeg": "^0.10.1"package.json 和 package-lock.json 都加入如下ffmpeg的版本配置&#xff1a; 1.2 把ffmpeg安装到项目依…

深入探究MySQL游标(Cursor)

前言 MySQL游标&#xff08;Cursor&#xff09;是MySQL中用于处理查询结果的一种机制。游标允许我们在查询结果集中逐行处理数据&#xff0c;而不是一次性获取所有数据。这对于处理大量数据非常有用&#xff0c;因为它可以减少内存消耗并提高性能。在MySQL中&#xff0c;游标主…

【源码】【Spring+SpringMVC+MyBatis】电子商城网上购物平台的设计与开发

学生成绩管理系统 系统功能开发环境开发技术前端技术后端技术 系统展示登录界面注册界面系统首页商品详情页下单界面付款界面购物车界面 源码获取↓↓↓↓&#xff1a; 源码可在后台私信联系博主或文末添加博主微信获取帮助 系统功能 登录、注册模块&#xff1a;如果用户第一次…

udp协议下的socket函数

目录 1.网络协议 2.网络字节序 3.socket编译接口 4.sockaddr结构体 5.模拟实现 1.socket函数 2.bind函数&#xff08;绑定&#xff09; 1.讲解 1.如何快速的将 整数ip<->字符串 2.ip地址的注意事项 3.端口号的注意事项 3.recvfrom函数 4.sendto函数 5.代码呈…

C++ Primer 第五版 第16章 模板与泛型编程

模板是C中泛型编程的基础。一个模板就是一个创建类或函数的蓝图或者说公式。当使用一个vector这样的泛型类型&#xff0c;或者find这样的泛型函数时&#xff0c;我们提供足够的信息&#xff0c;将蓝图转换为特定的类或函数。这种转换发生在编译时。 一、定义模板 1. 函数模板…

Airtest 使用指南

Airtest 介绍 准备工作 AirtestIDE 安装与启动: https://airtest.doc.io.netease.com/IDEdocs/getting_started/AirtestIDE_install/ 电脑端的准备工作完成后,对于手机端只需要打开允许USB调试,当首次运行时会提示安装PocoService,同意即可。 界面介绍

【CT】LeetCode手撕—53. 最大子数组和

目录 题目1-思路2- 实现⭐53. 最大子数组和——题解思路 3- ACM 实现 题目 原题连接&#xff1a;53. 最大子数组和 1-思路 动规五部曲 1. 定义 dp 数组 dp[i] 含义为&#xff1a;下标为 i 的数组的最大子数组和 2. 递推公式 因为所求的是最大子数组的和&#xff0c;即当前 n…

群辉其它远程访问方案(Cpolar篇)

目录 1、下载NAS套件安装包 2、手动安装 3、配置 4、访问 &#xff08;1&#xff09;网页 &#xff08;2&#xff09;手机管家 &#xff08;3&#xff09;助手 &#xff08;4&#xff09;DS File 群辉的远程访问&#xff0c;最标准的做法就是使用群辉自己的DDNS&#x…

飞腾派初体验(2)

水个字数&#xff0c;混个推广分&#xff0c;另外几个点还是想吐槽一下 - 1&#xff0c;上篇文章居然没有给开发板一个硬照&#xff0c;补上 - 飞腾派 自拍 2. 现在做镜像用Win32DiskImager的多吗&#xff1f;我记得当年都是dd命令搞定&#xff0c;玩树莓派的应该记得这个命令…

OpenAPI Typescript Codegen 的基本使用

下载 axios npm install axios OpenAPI Typescript Codegen 官网&#xff1a;https://github.com/ferdikoomen/openapi-typescript-codegen 安装 OpenAPI Typescript Codegen npm install openapi-typescript-codegen --save-dev–input&#xff1a;指定接口文档的路径、url …

安装Pygame

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Pygame是跨平台的Python模块&#xff0c;专为电子游戏设计&#xff08;包含图像、声音&#xff09;&#xff0c;创建在SDL&#xff08;Simple Direct…

【HarmonyOS - UIAbility组件和UI的数据同步】

简述 基于HarmonyOS的应用模型&#xff0c;可以通过以下几种方式来实现UIAbility组件与UI之间的数据同步。 使用EventHub进行数据通信&#xff1a;基于发布订阅模式来实现&#xff0c;事件需要先订阅后发布&#xff0c;订阅者收到消息后进行处理。使用globalThis进行数据同步…

【Linux】进程控制2——进程等待(waitwaitpid)

1. 进程等待必要性 我们知道&#xff0c;子进程退出&#xff0c;父进程如果不管不顾&#xff0c;就可能造成"僵尸进程”的问题&#xff0c;进而造成内存泄漏。另外&#xff0c;进程一旦变成僵尸状态&#xff0c;那就刀枪不入&#xff0c;“杀人不眨眼”的kill -9 也无能为…

Git基础指令(图文详解)

目录 Git概述Git基础指令Linux系统操作指令 Git软件指令1.配置信息2.名称和邮箱3.初始化版本库4.向版本库中添加文件5.修改版本库文件6. 查看版本库文件历史 7.删除文件8.恢复历史文件 Git概述 Git基础指令 Linux系统操作指令 Git是一款免费、开源的分布式版本控制系统&…

MPLS工作过程

数据层面&#xff1a; 1) 没有 MPLS 协议&#xff0c;基于 FIB 表正常转发即可 2) 名词&#xff1a;MPLS domain——MPLS 的工作半径 edge LSR(PE)——边界标签交换路由器 工作 mpls 域的边缘&#xff0c;连接域外设备 …

【Redis】安装和命令行客户端

https://www.bilibili.com/video/BV1cr4y1671t https://www.oz6.cn/articles/58 redis 非结构化有&#xff1a; 键值类型(Redis)文档类型(MongoDB)列类型(HBase)Graph:类型(Neo4j) 扩展性&#xff1a;水平即为分布式扩展 redis特征 键值&#xff08;key-value&#xff09;型…