C++ 离散化 算法 (详解)+ 例题

这篇具有很好参考价值的文章主要介绍了C++ 离散化 算法 (详解)+ 例题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、性质

  • 无限空间中有限的个体映射到有限的空间中去,以此提高算法的空间效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的压缩。

  • 适用范围:数的跨度很大,用的数很稀疏

  • 例如:值域:1~10^9, 个数:10^5,值域很大,但是用到个数相对很少,这个时候就可以离散化

    • 比如:将

      a[i] : 1 3 100 2000 50000//这里需要注意可以离散化的前提是数组元素必须是有序的
        i  : 0 1  2    3    4  //上面数字映射(离散化)后对应的下标

2、实现方式

  • 我觉得离散化(映射)最大的难点是前后映射关系,如何能够将不连续的点映射到连续的数组的下标。此处的解决办法就是开辟额外的数组alls[])存放原来的数组下标(被离散化的数的下标)。

  • 手动模拟如下:

    • 对于一组数如 :[1,3,2000,50000,-99,2000,3,30],首先排序去重后----->[-99,1,3,30,2000,50000]
      从排序去重后数组可以得到关系:-99 --> 0, 1 --> 1 , 3 --> 2, 30 -->3 ..........
      上面对应的0,1,2,3,......都是此数字映射后对应的相对下标
    • 离散化基本步骤可分为:

      1、离散化一定是有序的去离散化(排序)

      2、alls[]中可能存在重复元素(所以 去重)

      3、 如何算出X求映射的下标)离散化后的值 (二分查找)

      注意:对于上述第三条,可以理解为去找这个数映射后的数组下标。

  • 代码模板:

    • vector<int> alls; //存储所有待离散化的值
      sort(alls.begin(),alls.begin());//将所有值排序
      alls.erase(unique(alls.begin(),alls.end()),end());//去掉重复元素
      ​
      //二分求出X对应的离散化的值(数组下标)
      int find(int x)//找到第一个(最小)大于等于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;//这里加1映射到(1,2,3,4.......n),不加1的话映射到(0,1,2,3.....n)
      }
  • 关于代码中的unique函数和erase函数:

C++ 离散化 算法 (详解)+ 例题,算法学习笔记,算法,c++,数据结构如何自己实现unique函数:

例如:[1,1,2,2,2,3,4,5,5,5,6];
分为两步:
1、首先它是第一个元素
2、a[i] != a[i+1]

unique函数实现代码(双指针算法):

vector<int> ::interator unique(vector<int> &a)
{
    for(int i=0;j=0;i<a.size();i++)
    {
        if(!i || a[i] != a[i-1])
        {
            a[j++] = a[i];
        }
    }
    //a[0]~a[j-1]中存的所有a[i]中不重复的数
    rerturn a.begin()+j;
}

3、例题:802. 区间和 - AcWing题库

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

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

接下来 n 行,每行包含两个整数 x 和 c。

再接下来 m 行,每行包含两个整数 l 和 r。

输出格式

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

数据范围
−10^9≤x≤10^9
1≤n,m≤10^5
−10^9≤l≤r≤10^9
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5

  • 图解+分析(来源于大佬的题解分析):

  • C++ 离散化 算法 (详解)+ 例题,算法学习笔记,算法,c++,数据结构

 C++ 离散化 算法 (详解)+ 例题,算法学习笔记,算法,c++,数据结构

 

AC代码: 

#include<iostream>
#include<algorithm>
#include<vector>
#include<utility>

using namespace std;

typedef pair<int, int> PII;

//这里开30W是因为n个x操作和2*m个坐标
const int N = 3e5+10;
int a[N],s[N];//前缀和数组
int n,m;
vector<int> alls;//离散化数组(对应下标值)
vector<PII> add,query;

int find(int x)//找到第一个最小的大于等于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;
    }
    //如果+1映射从1,2,3........
    //否则从0,1,2,3、、、、、、、
    return r + 1;//返回映射
}

int main()
{
    cin >> n >> m;
    for(int i=0;i<n;i++)
    {
        int x,c;
        cin >> x >> c;
        //添加该位置加c的
        add.push_back({x,c});
        //把坐标放进离散化数组
        alls.push_back(x);
    }
    
    for(int i=0;i<m;i++)
    {
        int l,r;
        cin >> l >> r;
        //插入访问坐标
        query.push_back({l,r});
        //放入离散化数组里
        alls.push_back(l);
        alls.push_back(r);
    }
    
    //离散化板子
    sort(alls.begin(),alls.end());//排序
    //unique:返回去重后最后一个不重复元素的位置
    alls.erase(unique(alls.begin(),alls.end()),alls.end());//去重
    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)
    {
        int l = find(item.first),r = find(item.second);
        cout << s[r] - s[l-1] << endl;
    }
    return 0;
}

代码+样例模拟: 

C++ 离散化 算法 (详解)+ 例题,算法学习笔记,算法,c++,数据结构文章来源地址https://www.toymoban.com/news/detail-827048.html

到了这里,关于C++ 离散化 算法 (详解)+ 例题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构_复杂度讲解(附带例题详解)

    数据结构是计算机科学中研究数据组织、存储、管理和操作的方法和原则。它涉及到各种不同的数据类型和数据组织方式,包括数组、链表、树、图等。数据结构的设计和实现可以影响到程序的效率和可靠性,因此是计算机科学中非常重要的一个领域。 (数据结构是计算机存

    2024年02月07日
    浏览(36)
  • 【数据结构】浅谈数据结构-链表【思路+例题学习】

    🏆今日学习目标: 🍀学习算法-数据结构-链表 ✅创作者:贤鱼 ⏰预计时间:30分钟 🎉个人主页:贤鱼的个人主页 🔥专栏系列:算法 🍁贤鱼的个人社区,欢迎你的加入 贤鱼摆烂团 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中

    2024年01月21日
    浏览(39)
  • 【数据结构与算法】搜索算法(深度优先搜索 DFS和广度优先搜索 BFS)以及典型算法例题

    【数据结构与算法】系列文章链接: 【数据结构与算法】递推法和递归法解题(递归递推算法典型例题) 【数据结构与算法】系列文章链接: 【数据结构与算法】C++的STL模板(迭代器iterator、容器vector、队列queue、集合set、映射map)以及算法例题 【数据结构与算法】系列文章链

    2024年04月13日
    浏览(36)
  • 【学习笔记】数据结构算法文档(类C语言)

    1.1.1 线性表的顺序存储表示 1.1.2 顺序表中基本操作的实现 1.1.2.1 初始化 1.1.2.2 取值 1.1.2.3 查找 1.1.2.4 插入 1.1.2.5 删除 1.1.2.6 计数 1.2.1 单链表的定义和表示 ★ 关于结点 1.2.2 单链表基本操作的实现 1.2.2.1 初始化 1.2.2.2 取值 1.2.2.3 查找 1.2.2.4 插入 1.2.2.5 删除 1.2.2.6 前插法创建单

    2024年02月07日
    浏览(35)
  • 【软考程序员学习笔记】——数据结构与算法基础

    目录  🍊一、数据结构概念和分类 🍊二、数组特点存储方式 🍊三、矩阵 特殊矩阵 非特殊矩阵 🍊四、栈和队列 🍊 五、二叉树的性质 🍊六、二叉树的遍历 (1)前序遍历(先根遍历,先序遍历) (2)中遍历(中根遍历) (3)后序遍历(后根遍历,后序遍历) 🍊七、二叉排序树 🍊八、

    2024年02月12日
    浏览(50)
  • C++数据结构与算法详解:链表、栈、队列、树、二叉树和图结构的实现与应用

    链表是一种常见的数据结构由一系列节点按顺序连接而成,一般每个节点包含一个数据元素和一个指向下一个节点的引用。 链表有多种类型: 单向链表:每个节点只有一个指向下一个节点的引用 双向链表:每个节点有一个指向前一个节点和一个指向后一个节点的引用 循环链

    2024年02月04日
    浏览(36)
  • 数据结构(c++语言版) 邓俊辉 第五章:二叉树学习笔记

    5.1二叉树及其表示         树是由节点和边组成的。 1.有根树         树是由顶点(vertex)和边(edge)组成。树的每个顶点也叫节点(node)。 2.深度与层次         由树的连通性,每一节点与根都有一条路径相连:根据树的无环性,由根通往每个节点的路径必然唯一。  

    2024年02月13日
    浏览(34)
  • 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

    图的遍历指从图中某一顶点出发(任意一个顶点都可以作为访问的起始顶点),按照某种遍历方法,对图中所有的顶点访问一次且只访问一次。图与树不一样,其中一个顶点可能与多个顶点相连,所以需记录已访问过的顶点,当访问一个顶点后,考虑如何选取下一个要访问的

    2024年02月05日
    浏览(39)
  • 数据结构与算法之美学习笔记:48 | B+树:MySQL数据库索引是如何实现的?

    本节课程思维导图: 作为一个软件开发工程师,你对数据库肯定再熟悉不过了。作为主流的数据存储系统,它在我们的业务开发中,有着举足轻重的地位。在工作中,为了加速数据库中数据的查找速度,我们常用的处理思路是,对表中数据创建索引。那你是否思考过,数据库

    2024年01月16日
    浏览(59)
  • 机器学习 C4.5算法原理 + 决策树分裂详解(离散属性+连续属性) 附python代码

    一.C4.5算法的简介: C4.5并不是单单一个算法而是 一套算法 ,主要用于对机器学习和数据挖掘中的分类问题。它是一种有监督的学习,也就是说对于该算法我们需要 先给它们提供一个数据集 ,这个数据集包含多个实例,每个实例都包含多个属性,该实例用这些属性描述, 根

    2024年02月08日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包