离散化
在一些问题中,我们只关心 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
第二种方法
第二种方式其实就是排序之后,枚举着放回原数组
用一个结构体存下原数和位置,按照原数排序
我结构体里面写了个重载,也可以写一个比较函数
最后离散化后数在 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
两种不同的方法,一种对于重复的数据会按照日常生活中的并列来离散,一种是直接按顺序排序,可以根据题意灵活运用。