离散化处理
写在前面:离散化是对一堆元素进行操作,通过改变他们的大小,但不改变他们的大小关系,这种做法往往可以节省空间,减低时空复杂度。本文参考博客:HolseLee
举个例子理解离散化究竟是什么操作:
比如一个数组{6,7,11,12},保证他们两两之间的大小关系即可,那么通过离散化他得到的新数组就是{1,2,3,4}。当然离散化的结果不知这一种,要根据题意来具体分析要求什么样离散化的结果。
离散化的方式:
一般离散化分为两种:1.一种是对付有重复元素的离散化。2.另一种是对付无重复元素的离散化(复杂度低于第一种)。
1.应对有重复元素的离散化方法:
下面代码要用到两个stl函数:
1.unique()函数: 我之前在博客写过:链接地址
2.lower_bound()函数: 这个很好解释,lower_bound(起始地址,结束地址,要查找的数值) ,返回的是数值 第一个 出现的位置。
#include <bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
return a<b;
}
int main()
{
int n;
scanf("%d",&n);
int a[n+4],t[n+4];
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
t[i]=a[i];
}
sort(t+1,t+1+n,cmp);
int m=unique(t+1,t+1+n)-(t+1);//unique(t+1,t+1+n)是去重后数组的末地址,(t+1)是初始地址。
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(t+1,t+m+1,a[i])-t;//lower_bound()函数寻找下标最小的位置
}
for(int i=1;i<=n;i++)
{
printf("%d ",a[i]);
}
return 0;
}
2.对付无重复元素的离散化方法(复杂度优于第一种方法)
const int N=1e5+7;
struct Node{
int v,id;
bool operator < (const Node a)const{
return v<a.v;}//排序用
}a[N];
int n,rank[N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].v;
a[i].id=i;}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
rank[a[i].id]=i;
}
这种方法直接用结构体存储原本的数列的元素的位置,然后排序以后将他们再重新赋值。那么rank[]就是结构体a[]离散化后的结果。
举例:
v: 3 6 5 10 8
id:1 2 3 4 5
排序以后:
v: 3 5 6 8 10
id:1 3 2 5 4
所以离散化以后:
v: 3 5 6 8 10
id:1 3 2 5 4
rk:1 2 3 4 5
在按原来的顺序排列:
v: 3 6 5 10 8
rk:1 3 2 5 4