zoukankan      html  css  js  c++  java
  • 离散化(学习笔记)

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

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

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

    原数据: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大法

    模板:

    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;//索引
    

    可能直接看代码不太好理解,下面我给出一组例子来解释:

    假设有7个元素,分别为: 4 3 6 100 3 5 6

    b数组sort排序后为: 3 3 4 5 6 6 100

    unique去重后b数组为: 3 4 5 6 100 6 100

    (其实我们大可不必管b数组的变化,它只是a数组离散化的辅助数组,后面又用不上它)

    sum表示不重复元素的个数,即为5;

    a数组索引后: 2 1 4 5 1 3 4

    (1映射到原序列对应最小的元素3.......5映射到原序列对应最大的元素100)

    例:洛谷P4168 蒲公英(这题的正解其实是离散化后分块,但是我太蒻了,不会!)

    题目描述:

    在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关。

    为了简化起见,我们把所有的蒲公英看成一个长度为n的序列((a_1,a_2...a_n)),其中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]);


    #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;
    }
    

    离散化一般都只是作为辅助,在正式的算法开始之前对数据进行预处理的操作(上面这道题就是个极好的例子);

  • 相关阅读:
    txt换行追加写入
    np.unique( )的用法
    生成自己想要的任意颜色的图片
    183. 木材加工
    575. 字符串解码
    364. 接雨水 II
    255. Multi-string search
    433. 岛屿的个数
    591. 连接图 III
    918. 三数之和
  • 原文地址:https://www.cnblogs.com/PPXppx/p/9864949.html
Copyright © 2011-2022 走看看