ACM常用操作-离散化处理

本文介绍离散化的概念及其两种主要实现方法:适用于有重复元素和无重复元素的数组。通过实例展示如何使用C++实现离散化过程,帮助读者理解和应用离散化技术以优化算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

离散化处理


写在前面:离散化是对一堆元素进行操作,通过改变他们的大小,但不改变他们的大小关系,这种做法往往可以节省空间,减低时空复杂度。本文参考博客:HolseLee


举个例子理解离散化究竟是什么操作:

比如一个数组{6,7,11,12},保证他们两两之间的大小关系即可,那么通过离散化他得到的新数组就是{1,2,3,4}。当然离散化的结果不知这一种,要根据题意来具体分析要求什么样离散化的结果。


离散化的方式:

一般离散化分为两种:1.一种是对付有重复元素的离散化。2.另一种是对付无重复元素的离散化(复杂度低于第一种)。

1.应对有重复元素的离散化方法:

下面代码要用到两个stl函数:
1.unique()函数: 我之前在博客写过:链接地址
2.lower_bound()函数: 这个很好解释,lower_bound(起始地址,结束地址,要查找的数值) ,返回的是数值 第一个 出现的位置。

#include <bits/stdc++.h>
using namespace std;
bool cmp(int a,int b)
{
    return a<b;
}
int main()
{
    int n;
    scanf("%d",&n);
    int a[n+4],t[n+4];
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        t[i]=a[i];
    }
    sort(t+1,t+1+n,cmp);
    int m=unique(t+1,t+1+n)-(t+1);//unique(t+1,t+1+n)是去重后数组的末地址,(t+1)是初始地址。
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(t+1,t+m+1,a[i])-t;//lower_bound()函数寻找下标最小的位置
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",a[i]);
    }
    return 0;
}

2.对付无重复元素的离散化方法(复杂度优于第一种方法)

    const int N=1e5+7;
    struct Node{
      int v,id;
      bool operator < (const Node a)const{
        return v<a.v;}//排序用
    }a[N];
    int n,rank[N];
    int main()
    {
      cin>>n;
      for(int i=1;i<=n;i++){
        cin>>a[i].v;
        a[i].id=i;}
      sort(a+1,a+n+1);
      for(int i=1;i<=n;i++)
        rank[a[i].id]=i;
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值