离散化

离散化:
概念:把一些很离散的点个重新分配,使它们尽量集中.
如在1e10的范围中取1e4个数据,如果不进行离散化,则要开辟1e10的空间,而实际上只要1e4的空间就可以
装下每次取出的数据,所以可通过离散化来集中这些数据.
离散化的本质就是建立一个映射关系,即第n大的数字对应是几,如一组数6,2,4,666,48,则我们只要建立出
映射关系:6--3 2--1 4--2 666--5 48--4即是进行离散化

法一: 用一个辅助的数组把所有要离散的数据存下来,然后进行排序(为了之后的二分).再进行去重,因为
要保证相同的元素在离散化后数字相同,再用二分把离散化后的数字放回原数组
代码实现:

int cast[maxn],arr[maxn],cnt,n;
for (int i=1;i<=n;i++) {
    scanf("%d",&arr[i]);
    cast[i]=arr[i];
} 
sort(cast+1,cast+n+1);
cnt=unique(cast+1,cast+n+1)-(cast+1);
for (int i=1;i<=cnt;i++) {
    arr[i]=lower_bound(cast+1,cast+cnt+1,arr[i])-cast;
}

以上得到的代码cast为所存的原数组的值,而arr存的是对应的大小下标值

 

法二:用一个结构来储存这个值的下标,这样就不用另外存一个数字,来储存两次这批数
代码实现:

struct node{int val;int id;}ns[MAX_N];
int cast[MAX_N];
for (int i=1;i<=n;i++) {
    scanf("%d",ns[i].val);
    ns[i].id=i;
} 
sort(ns+1,ns+n+1);
for (int i=1;i<=n;i++) {
    cast[ns[i].id]=i; 
}

此处cast存的是大小下标值,ns[i].id存的是原下标的值

 

法三:用map数据结构来实现离散化:
分析:定义一个map型结构mp,其中mp[i]=j;i表示这个数字是多少,j表示这个数所在的大小位置
代码实现:

map<int,int> mp;
int n,c[maxn],st[maxn];
for (int i=1;i<=n;i++) {
    scanf("%d",&c[i]); 
    st[i]=c[i];
}
sort(st+1,st+n+1);
for (int i=1;i<=n;i++) mp[st[i]]=i;

 

所以对于一个无序数组c,我们找c中任意一个数都可以快速知道它是第几大的数,且mp.size()的值就是
数组c的不重复的元素个数

 

 

法一的代码完整模板:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#define rep(i,s,n) for (int i = s; i <= n; ++i)
#define fi first
#define se second
typedef long long ll;
const int MAXN = ??;
using namespace std;
int arr[MAXN];
int cast[MAXN];
int n,new_n;
void discretization()
{
    sort(cast + 1, cast + 1 + n);
    new_n = unique(cast + 1, cast + 1 + n) - cast - 1;
    rep(i,1,n)
        arr[i] = lower_bound(cast + 1, cast + 1 + new_n, arr[i]) - cast;
}
int main()
{
    scanf("%d",&n);
    rep(i,1,n)
    {
        scanf("%d",&arr[i]);
        cast[i] = arr[i];
    }    
    discretization();
    rep(i,1,n)
        printf("%d ",arr[i]);
    return 0;
}

法二的代码完整模板:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#define rep(i,s,n) for (int i = s; i <= n; ++i)
#define fi first
#define se second
typedef long long ll;
const int MAXN = ??;
using namespace std;
struct node
{
    int val;
    int id;
}ns[MAXN];
bool com(const node& n1, const node& n2)
{
    return n1.val < n2.val;
}
int cast[MAXN];
int n;
void discretization()
{
    sort(ns + 1, ns + 1 + n, com);
    rep(i,1,n)
        cast[ns[i].id] = i;
} 
int main()
{
    scanf("%d",&n);
    rep(i,1,n)
    {
        scanf("%d",&ns[i].val);
        ns[i].id = i;
    }
    discretization();
    rep(i,1,n)
        printf("%d ",cast[i]);
}

法三的代码模板:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#define rep(i,s,n) for (int i = s; i <= n; ++i)
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN = 10;
map<int,int> m;
int n,new_n;
int arr[MAXN];
int cast[MAXN];
void discretization()
{
    sort(cast + 1, cast + 1 + n);
    new_n = unique(cast + 1, cast + 1 + n) - cast - 1;
    rep(i,1,new_n)
        m[cast[i]] = i;
}
int main()
{
    scanf("%d",&n);
    rep(i,1,n)
    {
        scanf("%d",&cast[i]);
        arr[i] = cast[i];
    }
    discretization();
    rep(i,1,n)
        printf("%d %d\n",arr[i],m[arr[i]]);
}

 

法三的一道实例题:
给定一个长度为N的数组,数组的N个元素已知,并从中取出K(K<=N)个数,请你寻找一个最优选法,使得这K
个数中互不相同的数达到最大,求这个最大值.
本题的数字的范围达到了1e10,但数组长度只达到了1e5,所以要离散化,使得原本1e10的空间集中到1e5,
本题便可通过map数据结构来进行实现(利用map有预留空间但不占能力,即你有存在这个值,这个空间才
会开起来,否则就不会开这个空间)
代码实现:

#include <bits/stdc++.h>
using namespace std;
const int MAX_N=300005;
int N,K;
int c[MAX_N];
map<int,int> mp;
int main() {
    scanf("%d%d",&N,&K);
    for (int i=1;i<=N;i++) scanf("%d",c[i]);
    for (int i=1;i<=K;i++) mp[c[i]]++;
    int ans=mp.size();
    for (int i=K+1;i<=N;i++) {
        mp[c[i]]++;
        mp[c[i-K]]--;
        if (mp[c[i-K]]==0) mp.erase(c[i-K]);
        ans=max(ans,(int)mp.size());//mp.size()即为不同数的个数  
    }
    printf("%d",ans);
}  

 

posted @ 2021-07-28 16:33  jue1e0  阅读(193)  评论(0)    收藏  举报