简单。
简单定义
把一些值域很大的正数映射到一个很小的范围内
适用范围
当题目中所给的数据为正数且值域很大(如,([1,10^{19}]))时,如果题目不要求对这些数本身进行操作并且不需要求具体的值,只需要比较它们大小的关系或其它不涉及具体数值的操作,那么可以对这个序列进行离散化处理。
离散化有一个很著名的应用就是用树状数组求逆序对。
具体做法
一个通用的做法是,把原序列复制一份到新序列里,然后把新序列排序后去重,最后通过 lower_bound 函数得到原序列中每个数的排名。
e.g.
原序列:1000 1000 114514 1919 1919 810 114514
复制、排序:810 1000 1000 1919 1919 114514 114514
去重:810 1000 1919 114514
相对排名:2 2 4 3 3 1 4
参考代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a[10001],b[10001],n,m;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(b+1,b+n+1); //排序
m=unique(b+1,b+n+1)-b-1; //去重
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b; //lower_bound函数二分查找大于等于x的第一个位置
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
return 0;
}
有时候必须去重,有时候可以不去重
然后还有一种写法,需要搞一个结构体,很麻烦。
掌握这一种写法足以应付这种题目。