声明:本文为博主原创文章,未经允许不得转载。如有问题,欢迎指正!
目录
离散化思想
第一种实现离散化的具体方法:
第二种实现离散化的具体方法:
离散化的目的就是把无限空间中有限的元素映射到有限的空间中去,同时不改变这些元素的相对大小。具体一点就是把一个序列中较大的数用它在序列中排序后的位次进行替代。如给定一个序列A为{530,999999,19,666,8888},经过离散化处理后就变为{2,5,1,3,4}。给定序列B为{9999,555,11,333,8888}经过离散化处理以后就变为{5,3,1,2,4}。
(一)unique()函数及lower_bound()函数介绍:unique和lower_bound()都作用在序列上,可以接收两个迭代器(或指针)l,r ,对下标处于[l,r)中的元素起作用。它们的头文件都是include
(二)unique(l,r)可以去除序列中的重复元素,并返回去重以后末尾元素的下一个位置。利用迭代器(或指针)的减法,可以计算序列去重以后序列中元素的个数n:
把一个vector去重: int n=unique(a.begin(),a.end())-a.begin();
把一个数组去重,元素存放在下标1~n:int n=unique(a+1,a+n+1)-(a+1);
需要注意的是,unique()去重是将数组或容器中“相邻的重复元素”去重, 它会把重复的元素添加到容器的末尾,因此数组或容器的大小并没有改变,unique()的返回值是去重后不考虑末尾重复元素后的尾地址。若要真正实现去重,就应该对数组或容器先排序,然后使用unique()获取尾地址,最后去掉尾地址后面的元素:
//去掉容器中重复元素的操作
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
(三)对于一个有序的序列,lower_bound(l,r,x)会在两个迭代器(或指针)指定的[l,r)区间进行二分查找,返回第一个大于等于x的元素的位置 的迭代器(或指针)。
在有序的int数组中查找大于等于x的最小整数下标:
int i=lower_bound(a+1,a+n+1,x)-a;
在有序的vector
a中查找大于等于x的最小整数下标: int i=lower_bound(a.begin(),a.end(),x)-a.begin();
(四)第一种方法具体操作:把原数组num复制到中间数组lsh中,并对lsh数组(sort)排序和(unique)去重。用lower_bound(lsh+1,lsh+n+1,num[i])-lsh获取num[i]的排名并赋值给num[i]即可。
//核心代码:
#include //头文件
//n原始数组大小 num原数组中的元素 lsh为一个中间数组 cnt离散化后数组的大小
int lsh[maxn],cnt,num[maxn],n;
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
lsh[i]=num[i]; //将原数组复制到lsh数组中
}
sort(lsh+1,lsh+n+1); //对lsh排序
cnt=unique(lsh+1,lsh+n+1)-(lsh+1); //去重后大小
for(int i=1;i<=n;i++)
num[i]=lower_bound(lsh+1,lsh+n+1,num[i])-lsh;
//lower_bound(lsh+1,lsh+n+1,num[i])-lsh;
//获取了num[i]的排名,将num[i]赋值为其对应的排名即可。
(一)第二种方法具体操作:定义结构体数组num存储原序列元素的值(val)和对应的下标(id)。对num依据val的值升序排列,经过排序后的num数组的下标i就是val在原数组中的排名。令原下标id处的值等于排名i即可:rank[num[i].id]=i 。
//核心代码:
#include
struct Node{
int id; //原序列元素的原始下标
int val; //原序列元素的值
}num[maxn]; //结构体数组
bool comp(Node a,Node b){ //自定义的结构体比较函数
return a.val