离散化

Posted ppxppx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了离散化相关的知识,希望对你有一定的参考价值。

最近碰到好多题都先要离散化处理一下,本蒟蒻全挂了~~

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:

原数据:1,999,100000,15;

处理后:1,3,4,2;

原数据:{100,200},{20,50000},{1,400};

处理后:{3,4},{2,6},{1,5};

————《百度百科》

首先真的不要被离散化这个名字吓到了,离散化就是一种简单的思想,而且它是有模板的;

我们一般什么时候会用到离散化呢?就是当题目的数据范围很大,我们不可能开那么大的数组(什么一亿十亿的)来存这些数据,但是这些数据元素的个数却不多(在我们能够接受的合理范围内),这时我们就可以对这些超级大的数据进行离散化了;

就像上述百度百科举的两个例子那样,对的!离散化的思想就是这么简单;

但不得不提一下,对数据进行离散化,一定要考虑的是我们只想知道这些数据之间的相对大小,而不太在意它们的绝对大小,怎么理解这句话呢?用百度百科的第一个例子:

1,999,100000,15;

这四个数据离散化后:

1,3,4,2

我们不难发现离散化后我们只能知道数据之间的相对大小,但无法确定它们的真实值;

离散化的三个步骤:

1 sort排序

2 unique去重

3 lower_bound索引

不得不感叹STL大法

模板:

int n;
for(int i=1; i<=n; i++){
    scanf("%d",&a[i]);
    b[i]=a[i];    //b[]是a[]的副本
}
sort(b+1,b+n+1);  //排序
int sum=unique(b+1,b+1+n)-b-1;  //去重
for(int i=1; i<=n; i++)
    a[i]=lower_bound(b+1,b+1+sum,a[i])-b;//索引

例:洛谷P4168 蒲公英
题目描述
在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 (a_1,a_2..a_n)(a1,a2..an),其中ai为一个正整数,表示第i棵蒲公英的种类编号。

而每次询问一个区间 [l,r],你需要回答区间里出现次数最多的是哪种蒲公英,如果有若干种蒲公英出现次数相同,则输出种类编号最小的那个。

注意,你的算法必须是在线的;

输入输出格式

输入格式:

第一行两个整数n,m ,表示有n株蒲公英,m次询问。

接下来一行n个空格分隔的整数(a_i),表示蒲公英的种类

再接下来m行每行两个整数(l_0,r_0);

我们令上次询问的结果为x(如果这是第一次询问,则x=0)。

令l=((l_0)+x?1)mod n+1,r=((r_0)+x?1)mod n+1,如果(l>r)交换l,r;最终的询问区间为([l,r]);

输出格式:

输出m行。每行一个整数,表示每次询问的结果。


#pragma GCC optimize(3)  
//因为枚举暴力,所以手动O3,不然过不了
#include<bits/stdc++.h>
using namespace std;
int a[50001],b[50001],t[50001];  
//a[]索引的值,b[]排序去重,t[]枚举暴力的桶子 
int main(){
    int n,m,ll,rr,l,r,x=0;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++){
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    sort(b+1,b+n+1);
    int sum=unique(b+1,b+1+n)-b-1;
    for(int i=1; i<=n; i++)
        a[i]=lower_bound(b+1,b+1+sum,a[i])-b;
  //离散化模板      
    for(int i=1;i<=m;i++){  //枚举
        memset(t,0,sizeof(t));
        scanf("%d%d",&ll,&rr);
        l=(ll+x-1)%n+1;
        r=(rr+x-1)%n+1;
        if(l>r) swap(l,r);
        for(int j=l;j<=r;j++){
            t[a[j]]++;
        }
        int max=0,place=0;
        for(int j=1;j<=sum;j++)
            if(t[j]>max){
                max=t[j];
                place=j;
            }  
        printf("%d
",b[place]);
        x=b[place];
    }
    return 0;
}

离散化一般都只是作为辅助,在正式的算法开始之前对数据进行预处理的操作;



以上是关于离散化的主要内容,如果未能解决你的问题,请参考以下文章

离散化的思想和它的两种代码与区别

数据离散化

AcWing 2014. 岛(离散化+差分)

Matlab的Simulink连续模型离散化代码自动生成C语言(简明教程)

基本算法——离散化

坐标离散化