离散化

离散化

赶紧胡一篇出来,免得到时候出锅。
毕竟离散化是权值线段树学习的基础。

定义

把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
————百度百科

原理

简单来说,给出 n(n105) 个数字 ai(ai109),如果在这时建立权值线段树很明显会 MLE,所以将其离散化,也就是表示为这些数字的相对大小
比如一个数组 {1,34,6,14,8}
根据数字之间相对大小关系,离散化之后就是:

11

62

83

144

345

实现

实现的过程要用到 STL 库中的 lowerbound 这个好东西。
lowerbound 的用处是:在给定的有序序列中找到第一个小于给定数的数的下标,这也就很好的起到了离散化的作用。

至于代码的实现,就是把所有数先全存在一个数组中,每次对于要提取的数,用 lowerbound 即可。

n=R();
for(int i=1;i<=n;i++){
    a[i]=R(),t[i]=a[i];
}sort(t+1,t+1+n);
m=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;
}

例题

Luogu P1496 火烧赤壁

给定一个白色数轴,每次将给定区间 [ai,bi] 染成白色。多次染色效果相同 ,求最后染色区间总长度。

如果在 ai,bi 都很小的情况下,就可以用一个数组表示整个数轴,数组中的元素 fi 表示的是长度为 1 的区间 [i,i+1] 是否被染色,然后模拟每个指令,枚举数组区间并对数组 f 赋值即可。
因为 ai,bi 均很大,所以要用到离散化
因为题目中有用的数字不多,所以两个端点内点统一处理即可。
比如区间 [1,1] 转化为 [1,2] 染色,最后统计答案是将区间 [1,2] 的长度记录为 2 即可。

#include <bits/stdc++.h> 
using namespace std;int R(){
	int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);return x;
}void W(int x){if(x>9)W(x/10);putchar(x%10+'0');}const int N=2e4+10;
int n,a[N],b[N],f[N<<1],dt,ct,d[N<<1],x,y;long long c[N<<1],ans;
int main(){
	n=R();for(int i=1;i<=n;i++)a[i]=R(),b[i]=R(),d[++dt]=a[i],d[++dt]=b[i];sort(d+1,d+1+dt);
	for(int i=1;i<=dt;i++)if(d[i]!=d[i-1]||i==1)c[++ct]=d[i];
	for(int i=1;i<=n;i++){
		x=lower_bound(c+1,c+ct+1,a[i])-c;
		y=lower_bound(c+1,c+ct+1,b[i])-c;
		for(int j=x;j<y;j++)f[j]=1;
	}for(int i=1;i<ct;i++)if(f[i])ans+=c[i+1]-c[i];cout<<ans<<endl;return 0;
}
posted @   AIskeleton  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示