算法 离散化

整数离散化

适用条件

  1. 适用于有序的整数序列
  2. 该序列的值域很大,该序列的数的个数很少
  3. 使用的是数的相对大小而非绝对大小

算法思路

原数组 a :

数组下标:0 1 2 3 4

数组元素:1 2 2 5 109

映射数组 :

数组下标:0 1 2 3

数组元素:0 1 2 3(从0开始映射)

1 2 3 4(从1开始映射)

原理

  1. 将数据从数组a中复制到b数组,对b排序
  2. 给b去重
  3. 将b的下标作为象征,将a数组每个元素使用二分查找在b中找到,并用b的下标值替换a数组的元素值。

这样就完成了离散化操作

存在的问题

  1. a 数组中可能存在重复的元素 去重
  2. 如何算出 a 数组中每个元素离散化后的值 二分

其实就是找出在 a 数组中的下标是多少

模板

C

#include<studio.h>

int main()

{

int a[100]={0};

int n;

scanf("%d",&n);

for(int i=0;i<n;i++)

scanf("%d",&a[i]);

for(int j=0;j<n-1;j++){

for(int k=0;k<n-j-1;k++){

if(a[k]>a[k+1]){

int t=a[k];

a[k]=a[k+1];

a[k+1]=t;

}

}

}

int i=0,j=1;

int len=n;

while(i>=len-1 && j>=len-1){

while(a[i]!=a[j] && j<len){

i=j;

j++;

}

while

}

C++

需去重

vector<int> alls; //存储所有待离散化的值

sort(alls.begin(),alls.end()); //将数组中所有值排序

alls.erase(unique(alls.begin(),alls.end()),alls.end()); //去掉重复元素

//unique()函数将数组中所有元素去重,并且返回去重之后数组的尾端点的下标,erase()函数将返回的尾端点和数组末尾之间的数据去掉

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; //返回下标,r+1 表示从1开始映射,r 表示从0开始映射

}

具体参考下面区间和例题

无需去重

一边插入一边映射,类似于用二分优化插入排序。

使用插入排序方法,将数轴上的位置的相对大小作为判断依据进行排序,在每次接收时对数据进行同步处理,从第二个接收开始,先查看在该数组中,是否对此位置进行过操作,用二分查找进行判断,如果有,直接在对应位置上的数值进行增加,如果没有,使用插入排序中的插入操作把该数据直接插入数组中,这样的话,对于整个数组就不会有重复位置,即在数轴上没有相同的位置,因为会先进行查找,如果发现对某个位置已经进行过操作时,直接将其数值增加。所以在整个数组中没有一个相同的在数轴上的位置,并且是按照相对大小进行排序的,始终是有序的。

如何实现unique()函数

返回值

返回的是一个vector<int>的迭代器

基本实现思路:双指针算法

什么样的元素是不同的:排好序之后,1.它是第一个元素 2.a[i]!=a[i-1]

代码

vector<int>::iterator unique(vector<int> &a)

{

int j=0;//存下当前存到第几个数,j <= i

for(int i=0;i<a.size();i++)//遍历所有的数

if(!i || a[i]!=a[i-1])

a[j++]=a[i];//a[0]~a[j-1]就是所有a中不同的数

return a.begin()+j;

}

例题:区间和

假定有一个无限长的数轴,数轴上每个坐标上的数都是0。

现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。

接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。

输入格式

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

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

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

输出格式

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

数据范围

−10e9≤x≤10e9,

1≤n,m≤10e5,

−10e9≤l≤r≤10e9,

−10000≤c≤10000

输入样例

3 3

1 2

3 6

7 5

1 3

4 6

7 8

输出样例

8

0

5

当数组下标比较小的时候(数据范围比较小),可以用前缀和来完成

当数据范围比较大的时候,用离散化来完成

代码

//读入所有操作,将用到的位置进行离散化
#include<iostream>
#include<vector>  
#include<algorithm>
using namespace std;
typedef pair<int, int> PII;   //PII将两个数绑定在一块,一个作为first,一个作为second
const int N = 300010;//插入操作是十万(n),查询操作是二十万(2m)
int n, m;
int a[N], s[N]; //a是用到的数组成的数组,s是前缀和数组
vector<int> alls;  //说明里面存储的是int类型,相当于一个int类型的数组,不用考虑数组长度,alls存的是所有用到的下标
vector<PII> add, query;//插入操作,是pair<int,int>类型的数组,add和query是名称
int find(int x) //求x的值离散化之后的结果,求所用到位置(x)离散化之后的值//其实就是对于排序、去重之后的alls数组(所有用到的位置),返回x的下标(从0算起)/下标+1(从1算起)
{int l = 0, r = alls.size() - 1; //size是返回vector中有多少个有效数据while (l < r){int mid = (l + r) >> 1;if (alls[mid] >= x)r = mid;elsel = mid + 1;}return r + 1;//映射到从1开始的自然数
}
int main()
{cin >> n >> m;for (int i = 0;i < n;i++){int x, c;cin >> x >> c;add.push_back({ x,c }); //向vector末尾加数据,调用pair类型alls.push_back(x); //所有的点放在alls中,包括数字的点和区间的点}for (int i = 0;i < m;i++){int l, r;cin >> l >> r;query.push_back({ l, r }); //每次询问的左端点和右端点放在query中alls.push_back(l);alls.push_back(r);}//去重sort(alls.begin(), alls.end());//排序,指向数组数组首元素的指针,指向数组末尾元素后一位指针,第三个是一个函数指针,也可以是函数对象【在类中对()进行重载】,仿函数,类似于函数,第三个参数用来制定排序规则alls.erase(unique(alls.begin(), alls.end()), alls.end());//unique()把数组中所有重复元素删去,把不重复的元素放到数组的前面,//返回的是新数组的一个最后位置,把新数组最后一个位置到原来数组末尾的数据删除,即去重//处理插入//erase()用来删除//处理插入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;
}

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

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

相关文章

SVD recommendation systems

SVD recommendation systems 为什么在推荐系统中使用SVD 一个好的推荐系统一定有小的RMSE R M S E 1 m ∑ i 1 m ( Y i − f ( x i ) 2 RMSE \sqrt{\frac{1}{m} \sum_{i1}^m(Y_i-f(x_i)^2} RMSEm1​i1∑m​(Yi​−f(xi​)2 ​ 希望模型能够在已知的ratings上有好的结果的…

【Rust】所有权的认识

所有权 所有程序都必须管理其运行时使用计算机内存的方式。一些语言中具有垃圾回收机制&#xff0c;在程序运行时有规律地寻找不再使用的内存&#xff1b;在另一些语言中&#xff0c;程序员必须亲自分配和释放内存。 Rust 则选择了第三种方式&#xff1a;通过所有权系统管理内…

【浅尝C++】C++类的6大默认成员函数——构造、析构及拷贝构造函数

&#x1f388;归属专栏&#xff1a;浅尝C &#x1f697;个人主页&#xff1a;Jammingpro &#x1f41f;记录一句&#xff1a;好想摆烂&#xff0c;又好想学习~~ 文章前言&#xff1a;本篇文章简要介绍C类的构造函数、析构函数及拷贝构造函数&#xff0c;介绍每个小点时&#xf…

Mysql中的引擎介绍(InnoDB,MyISAM,Memory)

MySQL引擎就是指表的类型以及表在计算机上的存储方式。 MySQL数据库及其分支版本主要的存储引擎有三种&#xff0c;分别是 InnoDB、MyISAM、 Memory&#xff0c;还有一些其他的&#xff0c;CSV、Blackhole等&#xff0c;比较少见&#xff0c;可以使用SHOW ENGINES语句来查看。结…

【ShardingSphere专题】SpringBoot整合ShardingSphere(一、数据分片入门及实验)

目录 前言阅读对象笔记正文一、ShardingSphere介绍1.1 ShardingSphere-JDBC&#xff1a;代码级别1.2 ShardingSphere-Proxy&#xff1a;应用级别1.3 横向对比图 二、ShardingSphere之——数据分片2.1 基本介绍2.2 分片的形式2.2.1 垂直分片2.2.2 水平分片 2.3 数据分片核心概念…

揭开 BFC 的神秘面纱:前端开发必知必会

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

DS八大排序之直接插入排序和希尔排序

前言 我们前面几期介绍了线性和非线性的基本数据结构。例如顺序表、链表、栈和队列、二叉树等~&#xff01;本期和接下来的几期我们来详解介绍各个排序的概念、实现以及性能分析&#xff01; 本期内容 排序的概念以及其运用 常见的排序算法 直接插入排序 希尔排序 一、排序的…

利用Spring Boot构建restful web service的详细流程

本文档构建一个简单的restful webservice&#xff0c; 在官网原文Getting Started | Building a RESTful Web Service (spring.io)的基础上进行操作 文章目录 一、项目创建流程1.1 创建项目1.2 创建资源表示类1.3 创建资源控制类 二、项目运行参考资料 一、项目创建流程 本文的…

Android flutter项目 启动优化实战(一)使用benchmark分析项目

背景描述 启动时间是用户对应用的第一印象&#xff0c;较慢的加载会对用户的留存和互动造成负面影响 在刚上线的B端项目中&#xff1a; 1.提高启动速度能提高整体流程的效率 2.提高首次运行速度能提高应用推广的初体验效果 问题描述 项目刚上线没多久、目前存在冷启动过程存在…

前端面试灵魂提问

1.自我介绍 2.在实习中&#xff0c;你负责那一模块 3.any与unknow的异同 相同点&#xff1a;any和unkonwn 可以接受任何值 不同点&#xff1a;any会丢掉类型限制&#xff0c;可以用any 类型的变量随意做任何事情。unknown 变量会强制执行类型检查&#xff0c;所以在使用一个…

【古月居《ros入门21讲》学习笔记】07_创建工作空间和功能包

目录 说明&#xff1a; 1. 工作空间(workspace) 结构&#xff1a; 2. 创建工作空间和功能包 创建工作空间 编译工作空间 创建功能包 设置环境变量 3. 注意 同一个工作空间下&#xff0c;不能存在同名的功能包&#xff1b; 不同工作空间下&#xff0c;可以存在同名的功…

【模电】晶闸管

晶闸管 结构和等效模型工作原理晶闸管的伏安特性晶闸管的主要参数额定正向平均电流 I F I\tiny F IF维持电流 I H I\tiny H IH触发电压 U G U\tiny G UG和触发电流 I G I\tiny G IG正向重复峰值电压 U D R M U\tiny DRM UDRM反向重复峰值电压 U R R M U\tiny RRM URRM 晶体闸流…