离散化 ---( 求区间和)

什么是离散化?

        离散化是将连续的数值范围映射到有限的、离散的数值集合的过程。在许多情况下,数据可能会存在多个重复值或范围较大的连续值。为了简化处理,尤其是处理区间查询和增量问题时,我们可以将这些值转换为一组有限的、唯一的值(即离散值),从而更高效地进行操作。

        例如,如果我们有一组数值 {1.1, 1.2, 1.15, 2.5},在离散化后,我们可能会将其映射为 {1, 2, 3} 这样的索引值,便于后续的操作。

为什么要学离散化?

  1. 降低时间复杂度:处理连续的数据可能导致算法的时间复杂度急剧增加。通过离散化,我们可以将问题转化为处理较小的离散集,从而大大提高算法的效率。

  2. 节省空间:在许多应用中,尤其是对于大规模数据,存储每个连续值可能占用大量的空间。离散化有助于减少需要存储的数据量,使得内存使用更加高效。

  3. 简化问题:离散化能够将复杂的问题分解为基础操作,比如通过离散化后的索引数组,可以更容易地实现前缀和、区间查询等常见算法。

  4. 易于去重和排序:在进行统计分析时,我们常常需要去除重复的数值或对数据进行排序。离散化可以降低重复数据的复杂度,使这些操作更为简单。

  5. 灵活应对动态数据:在处理增量更新和查询时,离散化提供了一种高效的方法来动态管理数据,从而能够实时响应用户的请求。 

问题描述

        假设我们有一系列的增量操作和询问操作。增量操作允许我们在某个点上增加一个值,而询问操作则用于查询某个区间内的总和。为了高效处理这些操作,我们需要进行离散化,避免处理大量的数字,转而处理相对较小的离散值。

 代码示例

 

import java.io.BufferedInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

/**
 * 区间和
 */
public class test1 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(new BufferedInputStream(System.in));
        int n = sc.nextInt(); //n次操作
        int m = sc.nextInt(); //m次询问
        int N = 300010; //因为需要将所有x,l,r存在数组中,这样就是n + 2m <= 300000
        int[] a = new int[N]; //从1开始,需要通过x找到离散量,然后+1,
        int[] s = new int[N]; //前缀和来做,所以需要从1开始记录a

        List<Integer> alls = new ArrayList<>(); //将所有的使用到的数存在alls中,比如x,l,r
        //但其中会有先后顺序的差别,以及重复,所以需要排序和去重
        List<Pairs> add = new ArrayList<>(); //用来存n次操作
        List<Pairs> query = new ArrayList<>(); //用来存m次询问

        for (int i = 0; i < n; i++) {
            int x = sc.nextInt(); // 读取下一个增量数值
            int c = sc.nextInt(); // 读取增量值
            add.add(new Pairs(x, c)); // 将增量操作存储到add列表
            alls.add(x); // 将x值存储到alls,待后续处理
        }


        for (int i = 0; i < m; i++) {
            int l = sc.nextInt(); // 读取查询的左边界
            int r = sc.nextInt(); // 读取查询的右边界
            query.add(new Pairs(l, r)); // 存储查询操作到query列表
            alls.add(l); // 将左边界l加入alls
            alls.add(r); // 将右边界r加入alls
        }

        //到此为止,alls中存好了所有会被用到的数轴上的点,开始进行离散化处理

        Collections.sort(alls);//排序
        int unique = unique(alls);//去重
        alls = alls.subList(0, unique); //去重后的数值只保留有效部分

        for (Pairs item : add) {
            int index = find(item.first, alls); // 找到x在离散化数组中的位置
            a[index] += item.second; // 更新相应位置的增量值
        }


        //前缀和
        for (int i = 1; i <= alls.size(); i++) s[i] = s[i - 1] + a[i];

        for (Pairs item : query) {
            int l = find(item.first, alls); // 找到查询左边界的位置
            int r = find(item.second, alls); // 找到查询右边界的位置
            System.out.println(s[r] - s[l - 1]); // 输出区间和
        }

    }

    //去重
    static int unique(List<Integer> list) {
        int res = 0;
        for (int i = 0; i < list.size(); i++) {
            if (i == 0 || list.get(i) != list.get(i - 1)) {
                list.set(res, list.get(i));
                res++;
            }
        }
        return res;
    }

    //二分
    static int find(int x, List<Integer> list) {
        int l = 0;
        int r = list.size() - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (list.get(mid) >= x) {
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        return l + 1; //因为要考虑到前缀和
    }
}

class Pairs {
    int first;
    int second;
    public Pairs(int first, int second) {
        this.first = first;
        this.second = second;
    }

}

 核心逻辑解释

1. 数据输入

        我们首先读取增量操作的次数 n 和询问操作的次数 m。然后,我们定义两个数组 a 和 s,其中 a 用于记录每个离散化值的增量,而 s 用于存储前缀和。

int n = sc.nextInt(); // n次操作
int m = sc.nextInt(); // m次询问
int[] a = new int[N]; // 存储离散化数值对应的增量
int[] s = new int[N]; // 存储前缀和

 2. 收集所有数值

        我们使用 alls 列表来收集所有在增量和询问过程中出现的数字,方便后续的离散化。将增量操作和查询操作中的数字放入 alls 中。

List<Integer> alls = new ArrayList<>();

3. 离散化处理

        对 alls 中的数字进行排序和去重,得到每个数字在离散化后对应的唯一索引。去重的实现通过 unique 方法完成,确保我们只保留有效的数字。

Collections.sort(alls); // 排序
int uniqueCount = unique(alls); // 去重
alls = alls.subList(0, uniqueCount); // 只保留有效部分

4. 更新增量

在确定了离散化对应的索引后,我们遍历 add 列表,更新对应的增量值到数组 a 中。

for (Pairs item : add) {
    int index = find(item.first, alls); // 找到离散化的索引
    a[index] += item.second; // 更新增量
}

5. 前缀和计算

我们接下来计算前缀和数组 s,以便能快速响应后续的查询请求。

for (int i = 1; i <= alls.size(); i++) 
    s[i] = s[i - 1] + a[i]; // 构建前缀和

6. 响应查询

        最后,我们通过 find 方法找到查询区间的左、右边界在离散化数组中的位置,然后利用前缀和快速计算区间和并输出结果。

for (Pairs item : query) {
    int l = find(item.first, alls); // 左边界
    int r = find(item.second, alls); // 右边界
    System.out.println(s[r] - s[l - 1]); // 输出区间和
}

总结

        用离散化的方式有效处理增量操作和区间查询问题。这种方法不仅减少了数据规模,还显著提升了查询效率,是解决类似问题时值得参考的思路。

        离散化在处理动态数据时,尤其是区间和、区间更新等问题中,具有非常广泛的应用,能够帮助我们更高效地完成各种统计任务。

        希望能为你提供一些启发,下面是代码的图片示例,这样看注释会更清楚一些……

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

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

相关文章

C++ const成员函数

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 C const引用常量 使用规则 引用常量对象&#xff1a;可以引用一个常量对象&#xff0…

zabbix基本概念与组件

文章目录 一、zabbix简介二、​​​​​​​zabbix构成三、​​​​​​​zabbix监控对象四、​​​​​​​zabbix常用术语五、 Zabbix 6.0 新特性1.Zabbix server高可用防止硬件故障或计划维护期的停机2.Kubernetes系统从多个维度采集指标 六、zabbix 工作原理1、主动模式2、…

基于飞桨paddle2.6.1+cuda11.7+paddleRS开发版的目标提取-道路数据集训练和预测代码

基于飞桨paddle2.6.1cuda11.7paddleRS开发版的目标提取-道路数据集训练和预测代码 预测结果&#xff1a; 预测影像&#xff1a; &#xff08;一&#xff09;准备道路数据集 下载数据集地址&#xff1a; https://aistudio.baidu.com/datasetdetail/56961 mass_road.zip …

基于SpringBoot + Vue的医院预约挂号系统(角色:用户、医生、管理员)

文章目录 前言一、详细操作演示视频二、具体实现截图三、技术栈1.前端-Vue.js2.后端-SpringBoot3.数据库-MySQL4.系统架构-B/S 四、系统测试1.系统测试概述2.系统功能测试3.系统测试结论 五、项目代码参考六、数据库代码参考七、项目论文示例结语 前言 &#x1f49b;博主介绍&a…

excel单元格增加可选下拉列表

excel单元格增加可选下拉列表 下拉设置&#xff1a;数据–数据验证-选择序列-填写来源&#xff08;来源数据用英文逗号分隔&#xff09;&#xff08;是,否&#xff09;- 区域应用&#xff1a;选定区域-数据验证-是-确认

【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法

目录 一、Floyd算法与A * 算法 1、Floyd算法 思想 伪代码 2、 A * 算法 思想 伪代码 二、经典题目 题目一&#xff1a;卡码网 97. 小明逛公园 题目链接 题解&#xff1a;Floyd 算法 题目二&#xff1a;卡码网 127. 骑士的攻击 题目链接 题解&#xff1a;A * 算法&a…

Windows系统修改Tomcat虚拟机内存参数

文章目录 I 修改Tomcat虚拟机内存参数基于tomcat管理程序进行配置基于setenv文件进行配置II 查看服务器状态/manager/status 查看服务器状态manager/jmxproxy 查询Tomcat指标I 修改Tomcat虚拟机内存参数 基于tomcat管理程序进行配置 查看堆内存分配情况: jmap -heap pid jst…

列表、数组排序总结:Collections.sort()、list.sort()、list.stream().sorted()、Arrays.sort()

列表类型 一.Collections.sort() Collections.sort()用于List类型的排序&#xff0c;其提供了两个重载方法&#xff1a; 1.sort(List<T> list) &#xff08;1&#xff09;List指定泛型时只能指定引用数据类型&#xff0c;也就是说无法用于基本数据类型的排序。 &am…

wsksvg - 优化升级,支持多进程处理文件和 SVG 图像转化

前言 在不断发展的前端技术中&#xff0c;图像的优化和处理始终是提升应用性能的关键。wsksvg 插件的最新版本在之前的基础上进行了重大升级&#xff0c;现支持多进程处理文件以及将 SVG 图像转化为多种其他格式的图片。这一功能的引入不仅提升了处理效率&#xff0c;还大幅度…

MySQL之内置函数

目录 一、日期函数 二、字符串函数 三、数学函数 四、其它函数 一、日期函数 常见的日期函数如下&#xff1a; 函数名称说明current_date()获取当前日期current_time()获取当前时间current_timestamp()获取当前时间戳date_add(date, interval d_value_type)在date中添加日…

Jenkins Pipeline 中通过勾选参数来控制是否构建 Docker 镜像

1.定义参数&#xff1a; 使用 booleanParam 定义一个布尔参数&#xff0c;示例如下 booleanParam(name: BUILD_DOCKER, description: 是否构建Docker镜像, defaultValue: false)2.使用参数&#xff1a; 在 stage 中&#xff0c;根据参数的值决定构建方式&#xff1a; stage(编…

如何把用过的试卷恢复?5个软件帮助你快速进行试卷清除

如何把用过的试卷恢复&#xff1f;5个软件帮助你快速进行试卷清除 要恢复或清除用过的试卷上的答案或标记&#xff0c;通常涉及去除笔记、擦除手写痕迹或处理扫描件中的内容。以下五款软件可以帮助你有效地清除试卷上的文字、答案或标记&#xff0c;并将其恢复到空白状态&…

云原生|浅谈云原生中的对象存储之MinIO 的使用

一、什么是对象储存 对象存储&#xff08;Object Storage&#xff09;以对象的形式存储和管理数据&#xff0c;这些对象可以是任何类型的数据&#xff0c;例如 PDF&#xff0c;视频&#xff0c;音频&#xff0c;文本或其他文件类型。对象存储使用分布式存储架构&#xff0c;数据…

大型语言模型:通过代码生成、调试和 CI/CD 集成改变软件开发的游戏规则

文章目录 1. 引言2. 代码生成2.1 提高开发人员的生产力2.2 训练与适应 3. 使用人工智能进行调试和修复错误3.1 提高准确性的创新工具3.2 定制解决方案 4. 无缝 CI/CD 集成4.1 CI/CD 集成人工智能&#xff1a;可靠部署的催化剂4.2 持续学习和改进4.3 缩小开发和运营之间的差距 5…

媒界:2025河南台球及配套设施展会3月举办

立足中原&#xff0c;辐射全国&#xff0c;壹肆柒中国国际台球产业博览会3月在郑州盛大举办&#xff1b; 2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff08;壹肆柒台球展&#xff09; The 2025 China (Zhengzhou) International Billiards Industry Expo …

数据库中间件Mycat

Mycat是基于Java编写的实现了MySQL协议的数据库中间件&#xff0c;可以将它看成一个数据库代理&#xff0c;可以直接用MySQL客户端工具访问。其核心功能是分库分表和读写分离。 MyCat 是基于阿里开源的 Cobar 产品而研发&#xff0c;Cobar 的稳定性、可靠性、优秀的架构和性能…

【JAVA开源】基于Vue和SpringBoot的学科竞赛管理系统

本文项目编号 T 047 &#xff0c;文末自助获取源码 \color{red}{T047&#xff0c;文末自助获取源码} T047&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

【Java 集合】List接口 —— ArrayList 与 LinkedList 详解

List接口继承自Collection接口&#xff0c;是单列集合的一个重要分支。 在List集合中允许出现重复的元素&#xff0c;所有的元素是以一种线性方式进行存储的&#xff0c;在程序中可以通过索引&#xff08;类似于数组中的元素角标&#xff09;来访问集合中的指定元素。另外&…

CSS清除浮动的多种方法

目录 非 VIP 用户可前往公众号回复“css”进行免费阅读 给浮动元素的祖先元素加高度 给 div 写一个 clear:both; 属性(margin 失效) clear:both; 隔墙法 clear:both; 内墙法 父级 div 定义伪类:after 和 zoom(推荐使用) overflow:hidden;(能够让 margin 生效) 非 …

九、成功版--windows上安装artifactory配置postgressql

centos上搞不定&#xff0c;windows上搞定了 现阶段是想用java写程序控制制品库&#xff0c;等以后研究多了需要写一些脚本的时候&#xff0c;在研究linux上安装artifactory&#xff08;公司就用的linux安装的配置mysql&#xff0c;有空对着配一下linux的&#xff09; 源码地…