离散化

  离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率 

那么举个栗子,某个题目告诉你有1e5个数,每个数大小不超过1e9,要你对这些数进行操作(比如并查集之类的)。那么肯定不能直接开1e9大小的数组,但是1e5的范围就完全没问题。在举个栗子,现在对{4,7,6,9}进行离散化,那么得到的结果是{1,3,2,4},也就是说,当我们并不需要这些数据具体是多少时,就只需要知道他们的相对大小就行了。

离散化的方法有两种,一种是有重复元素的,一种是没有出现重复元素的。使用的时候务必要分清。

第一种:有重复元素的离散

 1 const int maxn = 2e6+6;
 2 
 3 int t[maxn],a[maxn];
 4 int n;
 5 
 6 int main(){
 7     scanf("%d",&n);
 8     for (int i=1;i<=n;i++){
 9         scanf("%d",&a[i]);
10         t[i] = a[i];
11     }
12     sort(t+1,t+1+n);
13     int size = unique(t+1,t+1+n)-t-1;
14     for (int i=1;i<=n;i++){
15         a[i] = lower_bound(t+1,t+1+size,a[i])-t;
16     }
17     for (int i=1;i<=n;i++){
18         printf("%d ",a[i]);
19     }
20     return 0;
21 }

第二种:无重复元素的离散


这种方式的离散复杂度比第一种优秀,但是不可以处理重复的元素

 1 const int maxn = 2e6+6;
 2 
 3 struct Node{
 4     int v,id;
 5     bool operator < (const Node a)const{
 6         return v < a.v;
 7     }
 8 }a[maxn];
 9 
10 int Rank[maxn],n;
11 
12 int main(){
13     scanf("%d",&n);
14     for (int i=1;i<=n;i++){
15         scanf("%d",&a[i].v);
16         a[i].id = i;
17     }
18     sort(a+1,a+1+n);
19     for (int i=1;i<=n;i++){
20         Rank[a[i].id] = i;
21     }
22     for (int i=1;i<=n;i++){
23         printf("%d ",Rank[i]);
24     }
25     return 0;
26 }

这种方法直接用结构体存储原本的数列的元素的位置,然后排序以后将他们再重新赋值。那么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

原文地址:https://www.cnblogs.com/-Ackerman/p/11332893.html