• 离散化


    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目:      

                Problem A: ycz的离散化

    Description

    给你n个数,每个数的大小在long long范围内。
    请输出n个数升序排序(小的在前,大的在后)后,第k个数的排名

    Input

    第一行两个数n,k,n<=5e5,k<=n
    第二行n个数,每个数的权值在[0,1e15]之间

    Output

    输出一行一个整数,代表第k个数在升序排序之后的排名

    Sample Input

    7 6
    1 8 8 3 2 -5 6

    Sample Output

    1

    HINT

    解析:https://www.cnblogs.com/cytus/p/8933597.html

    法一:code:

    #include<bits/stdc++.h>
    #pragma GCC optimize(3)
    #define int long long
    #define fill(a,b) memset(a,b,sizeof(a))
    using namespace std;
    int k,n,a[500010],t[500010],rank[500010],m;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    signed main(){
        n=read(),k=read();
        for (int i=1;i<=n;i++){
            a[i]=read();
            t[i]=a[i];
        }
        sort(t+1,t+n+1);
        m=unique(t+1,t+n+1)-t-1;
        for (int i=1;i<=n;i++)
            a[i]=lower_bound(t+1,t+m+1,a[i])-t;
        printf("%lld",a[k]);
        return 0;
    }

     在这段代码中,a[]经过离散,范围就变成了m。解释一下,unique是c++自带的一个函数,表示对一个数列去重,然后返回不重复的元素个数,当然在后面要减去首地址(t+1)。那么这种离散化对于有重复元素的数列也可以适用,但复杂度相对后面要讲的第二种方法会高些。

      举个栗子

      {6,8,4,9,5,6,7,4},首先排序后得到{4,4,5,6,6,7,8,9},去重{4,5,6,7,8,9},然后原序列就变成了 离散(相当于存储从小到大的位置

           {3,5,1,6,2,3,4,1}。

    lower_bound( )upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。在从小到大的排序数组中,lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

    upper_bound()只是找第一个大于num的数字

    所以此题还可以写成:a[i]=upper_bound(t+1,t+m+1,a[i])-t;

    输出:a[k]-1 即可

    法二:code:

    #include<bits/stdc++.h>
    #pragma GCC optimize(3)
    #define int long long
    using namespace std;
    int k,n,t[500010],rank1[500010],m,ans,cnt;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    struct node{
      int v,id;
    }a[500010];
    bool cmp(node a,node b){
        return a.v<b.v;
    }
    signed main()
    {
      n=read(),k=read();
      for(int i=1;i<=n;i++){
        a[i].v=read();
        a[i].id=i;
       }
      sort(a+1,a+n+1,cmp);
      //int m=unique(t+1,t+n+1)-t-1;
      cnt=0;
      a[0].v=1ll*1e16;//要给a[0].v赋初值,否则当a[1].v==a[0].v==0时,直接输出0,WA了
        for(int i=1;i<=n;i++){
        if(a[i].v!=a[i-1].v){
            cnt++;
        }
        rank1[a[i].id]=cnt;
      }
      // for(int i=1;i<=n;i++)
      //      cout<<rank1[i]<<" ";
      //  cout<<endl;
        printf("%lld
    ",rank1[k]);
        return 0;
    }
    /*
    7 6
    1 8 8 3 2 -5 6
    
    8 3
    1 8 8 3 3 2 -5 6
    */

    如果不赋a[0].v初值,一组hank数据

    9 7
    1 8 8 3 3 2 0 0 6

    正确答案应为1

    不赋a[0].v初值的WA答案为0

    此方法类似于

    NOIP2013火柴排队

             来自于我的博客   

        欢迎大家阅读归并排序之逆序对   

     逃~

     
  • 相关阅读:
    守望先锋-生涯数据信息抓取的实现
    Norm 数据库操作竟然可以如此简单
    java中关于转义字符的一个bug
    在Java中==的一个坑
    人机ai五子棋 ——五子棋AI算法之Java实现
    MySQL数据库罕见的BUG——Can't get hostname for your address
    [疑难杂症]__关于cmd命令正确而显示不是内部指令的错误(ps:已解决)
    [疑难杂症]__点击win10屏幕最上方的边界会莫名其妙打开Internet Explorer浏览器,不胜其烦(2次ps:已解决!!!).
    [Java初探外篇]__关于正则表达式
    [java初探外篇]__关于StringBuilder类与String类的区别
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11536644.html
Copyright © 2020-2023  润新知