离散化的使用

什么是离散化

离散化本质上是一种哈希,它在保持原序列大小关系的前提下把其映射成正整数。它可以有效的降低时间复杂度。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。
 如果数字特别大的话,例如 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;
}
  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值