zoukankan      html  css  js  c++  java
  • 离散化

    先看一到例题

    给定 n 个数(可能相同),出现次数最多的数出现了多少次。(ai <= 10 ^ 9)

    嗯……这道题看似一道水题,只要开一个 vis 数组记录每一个数字出现的次数即可,比如 vis[a[i]]++。但是值得注意的是,ai可能非常大,这就导致 vis 数组会开不下,因此,就要用到离散化。

    大体来说,离散化就是将一串数字进行压缩,比如 g[1] = 1  g[2] = 3  g[3] = 100000 g[4] = 45, 将其离散化后, g[1] = 1  g[2] = 2  g[3] = 4 g[4] = 3,此时 g[i]  存的是每一个数在所有数的大小位置。上述中,45 是第三大的,所以原来存 45 的 g[4] 就变成了3。这样例题就好办了,因为此时的 g 就相当于 vis 数组,而这个数组最大长度一定小于等于 n。(可能有重复数字)对了,若想保留原来的数的话,只需另开一个数组记录。

    那离散化具体怎么实现呢?

    这里面讲两种做法

    1.

    首先我们需要开一个结构体来记录每一个数的初始值和在数组中的位置。然后创建一个指针,这个指针用来表示不同数字的个数。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn = 1e5 + 5;
     8 int n, a[maxn], g[maxn];    //g[] 来存值 
     9 struct node
    10 {
    11     int num, id;
    12     bool operator < (const node& other)const
    13     {
    14         return num < other.num;        //默认从小到大 
    15     }
    16 }t[maxn];
    17 int now = 0;
    18 int main()
    19 {
    20     scanf("%d", &n);
    21     for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    22     for(int i = 1; i <= n; ++i){t[i].num = a[i]; t[i].id = i;}
    23     sort(t + 1, t + n + 1);        //要离散,先排序 
    24     for(int i = 1; i <= n; ++i)
    25     {
    26         if(i == 1 || t[i].num != t[i].num) now++;    //如果是和前面不同的数,now++(因为已经排好序了) 
    27         g[now] = t[i].num; a[t[i].id] = now;        //此时的a[i]存的就是原来a[i]是第几小的数 
    28     }
    29     for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
    30     printf("
    ");
    31     for(int i = 1; i <= n; ++i) printf("%d ", g[i]);
    32     printf("
    ");
    33     return 0;
    34 }

    输入:

    5

    2 100 4 1 4

    输出:

    2 4 3 1 3 

    1 2 4 100

    此时我们还能发现,指针 now 不仅表示了有 now 个不同的数,也表示了第 now 小的数是什么

    稍微改一下,就是例题

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn = 1e5 + 5;
     8 int n, a[maxn], g[maxn], tot[maxn];    
     9 bool cmp(int a, int b)
    10 {
    11     return a > b;
    12 }
    13 struct node
    14 {
    15     int num, id;
    16     bool operator < (const node& other)const
    17     {
    18         return num < other.num;    
    19     }
    20 }t[maxn];
    21 int now = 0;
    22 int main()
    23 {
    24     scanf("%d", &n);
    25     for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    26     for(int i = 1; i <= n; ++i){t[i].num = a[i]; t[i].id = i;}
    27     sort(t + 1, t + n + 1);        
    28     for(int i = 1; i <= n; ++i)
    29     {
    30         if(i == 1 || t[i].num != t[i - 1].num) now++;    
    31         g[now] = t[i].num; a[t[i].id] = now;        
    32     }
    33     for(int i = 1; i <= n; ++i) tot[a[i]]++;
    34     sort(tot + 1, tot + n + 1, cmp);
    35     printf("%d
    ", tot[1]);
    36     return 0;
    37 }

    2.

    这种做法是我前最近学到的,不仅想法简单,而且实现起来也很方便。

    首先我们将所有数存到一个数组中,然后排个序,再去个重(用unique函数),最后用lower_bound查找每一个数的位置,即离散化后的值。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn = 1e5 + 5;
     5 int a[maxn], t[maxn];
     6 int main()
     7 {
     8     int n; scanf("%d", &n); 
     9     for(int i = 1; i <= n; ++i) {scanf("%d", &a[i]); t[i] = a[i];}
    10     sort(a + 1, a + n + 1);
    11     int _n = unique(a + 1, a + n + 1) - a - 1;         
    12     for(int i = 1; i <= _n; ++i)
    13         t[i] = lower_bound(a + 1, a + _n + 1, t[i]) - a;
    14     for(int i = 1; i <= n; ++i) printf("%d ", t[i]);
    15     return 0;
    16 }

    输入:

    7

    1 2 8 4 6 4 100

    输出:

    1 2 5 3 4 3 100

  • 相关阅读:
    python多进程(二)
    PLSQL配置
    sql语句之左连结
    点击lable标出现下拉搜索框及选择功能
    angularjs前端分页自定义指令pagination
    未经整理的工作中遇到的小问题
    晒一晒工作内容.....呵呵勿喷
    配置chrome支持本地(file协议)ajax请求
    html5+angularjs+bootstrap+springmvc+mybatis模糊查询Deme
    oracle的sql积累..&..decode函数使用
  • 原文地址:https://www.cnblogs.com/mrclr/p/8422975.html
Copyright © 2011-2022 走看看