离散化
离散化是一个非常常用的技巧,需要用到algorithm
库中的三个常用函数,此处顺便记录一下其用法。
函数简介
sort
用于将一个任意的无序数组在\(O(n\log n)\)时间内排好序。
用法(eg.将a[i]~a[n]中的元素降序排列),可自定义比较函数cmp。
bool cmp(int x,int y){
return x>y;
}
int main(){
sort(a+1,a+n+1,cmp);
return 0;
}
unique
用于数组元素的去重,注意unique实际上完成的事是把重复元素放在数组的末尾,所以去重后一定要获取新数组大小,方便之后的操作,时间复杂度为\(O(n)\)。
本质为迭代器,与sort
一样满足左闭右开的区间性质。
用法(eg.将a[i]~a[n]中的元素去重并统计剩余元素的大小)
int len=unique(a+1,a+n+1)-a-1;
lower_bound
用于在有序数列中\(O(\log n)\)查找元素位置(lower_bound
为查找序列中出现的第一个大于等于某元素的位置,upper_bound
为查找序列中出现的第一个严格大于某元素的位置),
本质为迭代器,与sort
和unique
一样满足左闭右开的区间性质。
用法(eg.在有序数组a中查找a[i]~a[n]中第一个大于等于x的数在a数组中的下标)
int pos=lower_bound(a+1,a+n+1,x)-(a+1);
综合运用
现在我们要对数组a进行离散化,流程一共有三个。
- 将a数组复制到辅助数组b中(在输入时就顺便处理了不算在流程中)
- 将辅助数组b排序
- 将辅助数组b去重并得到其去重后长度
- 将a数组的元素赋值为其在b中查找到第一个大于等于(其实这里是保证等于)它的元素的下标
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int Maxn=1e5+5;
int n,a[Maxn],b[Maxn];
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+n+1);
int m=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+m+1,a[i])-b;
cout<<a[i]<<" ";
}
return 0;
}
input:
5
11 4 51 4 1919810
output:
2 1 3 1 4