离散化详解(两种方法)

离散化

在一些问题中,我们只关心 n 个数字之间的相对大小关系,而不关心它 们具体是多少。
因此,我们可以用一种叫离散化的技术来将数字映射到 1 ∼ n 的整数, 从而降低问题规模,简化运算。
通常的实现方法是将所有数字排序,然后再重新遍历一遍所有的数字, 通过二分查找找到它们的 “排名”,然后用排名来代替对应的数字。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
//#define int __int128
using namespace std;
typedef long long ll;//全用ll可能会MLE或者直接WA,试着改成int看会不会A
const ll N=100000;
const ll INF=1e9+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;

template<typename T>void read(T &x)
{
    x=0;char ch=getchar();ll f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x*=f;
}

vector<ll>v;

ll n,a[N];
int main()
{
    scanf("%lld",&n);
    over(i,1,n)scanf("%lld",&a[i]);
    over(i,1,n)
        v.push_back(a[i]);
    sort(v.begin(),v.end());
    over(i,1,n)
    {
        a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
        printf("%lld   ",a[i]);
    }
    puts("");
    return 0;
}

输入输出:

6
500 400 300 300 100 200
6   5   3   3   1   2

第二种方法

第二种方式其实就是排序之后,枚举着放回原数组

用一个结构体存下原数和位置,按照原数排序

我结构体里面写了个重载,也可以写一个比较函数

最后离散化后数在 r a n k s [ ] ranks[] 里面

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
//#define int __int128
using namespace std;
typedef long long ll;//全用ll可能会MLE或者直接WA,试着改成int看会不会A
const ll N=100000;
const ll INF=1e9+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;

template<typename T>void read(T &x)
{
    x=0;char ch=getchar();ll f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}x*=f;
}

struct node
{
    ll data,id;
    bool operator<(const node &t)const{return data<t.data;}
}a[N];
ll n,m,ranks[N];
int main()
{
    scanf("%lld",&n);
    over(i,1,n)scanf("%lld",&a[i].data),a[i].id=i;
    sort(a+1,a+1+n);
    over(i,1,n)
    ranks[a[i].id]=i;
    over(i,1,n)
    printf("%lld   ",ranks[i]);
    return 0;
}

输入输出:

6
500 400 300 300 100 200
6   5   3   4   1   2

两种不同的方法,一种对于重复的数据会按照日常生活中的并列来离散,一种是直接按顺序排序,可以根据题意灵活运用。

发布了160 篇原创文章 · 获赞 150 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45697774/article/details/105418926