• 离散化


    先看一到例题

    给定 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

  • 相关阅读:
    netmeeting使用收集
    开始Nunit学习(1)
    数据库信息查询(作者不是我)
    2月到5月的总结
    最近学到的一些东西
    gridview无法绑定datarow[]的解决
    asp.net控件开发(二)简单属性
    javascript 获取页面高度(多种浏览器)(转)
    My Asp.net Ajax Trip(一) Using For UpdatePanel
    asp.net 控件开发(一)显示控件内容
  • 原文地址:https://www.cnblogs.com/mrclr/p/8422975.html
Copyright © 2020-2023  润新知