什么是离散化
离散化
本质上是一种哈希,它在保持原序列大小关系的前提下把其映射成正整数。它可以有效的降低时间复杂度。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。
如果数字特别大的话,例如
1
0
9
10^9
109的话,那么数组的空间就远远超过了题目所要求的空间,我们这时候就要用到"离散化"这个技巧解决这种问题。
怎么离散化
离散化就是把原数字用他们的相对大小来代替,顺序不变,不影响它们互相比较大小
。例如{
1
,
20000
,
10
,
300
,
89000000
1,20000,10,300,89000000
1,20000,10,300,89000000},相对大小是{
1
,
4
,
2
,
3
,
5
1,4,2,3,5
1,4,2,3,5};
二者如果比较逆序对之类的,前者需要较大的空间,而后者空间很小。那么怎么离散化呢,该怎么实现呢?
其实思路:先排序,再删除重复元素,最后就是索引元素离散化后对应的值;
代码实现离散化
离散化后的数组是a数组
struct point {
int num,va;
}st[N];
bool cmp (point x,point y) {
if (x.va!=y.va) return x.va<y.va;
return x.num<y.num;
}
void solve {
int n;cin>>n;
for (int i=1;i<=n;i++) {
cin>>st[i].va;
st[i].num=i;
}
sort (st+1,st+1+n,cmp);讲数组排序
for (int i=1;i<=n;i++) a[st[i].num]=i;//最核心的一步
}
离散化例题
下面是一道利用离散化结合树状数组的例题
原题链接:点击跳转
一道逆序对的例题,这个例题可以用归并排序的方法写,也可以用树状数组的方法写,如果要用到树状数组来写的话,就要用到离散化,因为数据比较大。这里我们用到的方法是树状数组。
#include <bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define fi first
#define se second
#define PII pair <int,int>
#define ALL(x) x.begin(),x.end()
#define lowbit(x) (x&(-x))
using namespace std;
const int N = 1e6+5;
int a[N];
int chafen[N];
int tree[N];
int n,m;
struct jiegou {
int x,y;
}b[N];
bool cmp (jiegou qwe,jiegou asd) {
if (qwe.x!=asd.x) return qwe.x<asd.x;
return qwe.y<asd.y;
}
void update (int x,int d) {
while (x<=n) {
tree[x]+=d;
x+=lowbit(x);
}
}
int sum (int x) {
int ans=0;
while (x>0) {
ans+=tree[x];
x-=lowbit(x);
}
return ans;
}
void solve () {
cin>>n;
for (int i=1;i<=n;i++) {
cin>>b[i].x;
b[i].y=i;
}
sort (b+1,b+1+n,cmp);
for (int i=1;i<=n;i++)
a[i]=b[i].y;
// for (int i=n;i>=1;i--) {
// cout<<a[i]<<' ';
// }
int res=0;
for (int i=n;i>=1;i--) {
update(a[i],1);
res+=sum(a[i]-1);
}
cout<<res;h
return ;
}
signed main () {
IOS;
int T =1;
// cin>>T;
while(T--) solve ();
return 0;
}