Part one:基本概念
离散化,大家可以简单的理解为把大的内容通过某种方式压缩成小的内容。在OI竞赛
中,离散化通常是在主算法已经写好的情况下,作为辅助工具进行的。
离散化有很多种,今天讲最简单的一种:整数离散化(当然,这名字是编者起的,并非专业)。
Part two:整数离散化
所谓整数离散化,就是将一组大的数字进行重新编号,使得其范围大大减小。同时,重新编号不能破坏原有数字的大小关系,而且,为了方便处理,我们通常给它们编号为整数。
举个例子:比如原数字为 ,我们可以把它们重新编号为 ,在它们的大小关系没有被破坏的前提下,我们将它们的范围大大缩小。
当然,因为我们把原数字修改了,所以离散化之后,有些问题便无法求解(如判断是否有原数字等于给定数字)。
Part three:如何整数离散化
我们把原数组排序,然后从小到大一一编号即可,最后按照原顺序重新排回来。
【代码】:
struct node{
int id,number,num;
}a[N];int n;
inline bool cmp1(node a,node b){
return a.number<b.number;
}
inline bool cmp2(node a,node b){
return a.id<b.id;
}
inline void discretization(){
// 离散化原数组
sort(a+1,a+n+1,cmp1);
a[0].number=a[1].number-1;
for(int i=1;i<=n;i++)
if (a[i].number>a[i-1].number)
a[i].num=a[i-1].num+1;
else a[i].num=a[i-1].num;
sort(a+1,a+n+1,cmp2);
}
顺带一提:离散化后,所有数字的范围最最多是 ( 为数字个数)。
Part four:离散化的应用
【收集雪花】:
不同的雪花往往有不同的形状。在北方的同学想将雪花收集起来,作为礼物送给在南方的同学们。一共有
个时刻,给出每个时刻下落雪花的形状,用不同的整数表示不同的形状。在收集的过程中,同学们不希望有重复的雪花。你可以从任意
时刻开始,在
时刻停止。
到
时刻中间的雪花也都将被收集。他们希望收集的雪花最多。
【思路】: 如果
范围小,完全可以用尺取法搞定。
范围大,但是只有它们的大小关系对于我们是有用的,所以我们可以离散化。
【代码】:
const int N=1e6+100;
struct node{
int id,number,num;
}a[N];int n,ans;bool b[N];
inline bool cmp1(node a,node b){
return a.number<b.number;
}
inline bool cmp2(node a,node b){
return a.id<b.id;
}
inline void discretization(){
// 离散化原数组
sort(a+1,a+n+1,cmp1);
a[0].number=a[1].number-1;
for(int i=1;i<=n;i++)
if (a[i].number>a[i-1].number)
a[i].num=a[i-1].num+1;
else a[i].num=a[i-1].num;
sort(a+1,a+n+1,cmp2);
}
inline void Determining(){
memset(b,false,sizeof(b));
for(int l=1,r=1;l<=n;l++){
b[a[l-1].num]=false;
while (r<=n&&!b[a[r].num]){
b[a[r].num]=true;r++;
}
ans=max(ans,r-l);
}
}
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
inline int hpwwzyy2012(){
n=read();
for(int i=1;i<=n;i++){
a[i].id=i;
a[i].number=read();
}
discretization();
Determining();
printf("%d",ans);
return 0;
}
int main(){
// freopen("t1.in","r",stdin);
return hpwwzyy2012();
}