zoukankan      html  css  js  c++  java
  • 有序数列第K小

    有序数列第K小

    题目描述

    给出两个长度分别为(n,m)的单调非递减数列,求出它们合并后的第(k)小值。

    输入输出格式

    输入格式:

    第一行三个数,(n,m,k)如题意所述;

    第二行(n)个数,依次为数列1;

    第三行(m)个数,依次为数列2;

    输出格式:

    一个数,表示合并后的第(k)小值。

    说明

    对于所有数据,(kle n+mk≤n+m , a_ile 10^8),时间限制200ms。


    这个题其实考察的是(logk)的分治做法

    对当前的两个序列,左指针为(la,lb),右指针为(ra,rb),求当前的第(k)小值。

    把第(k)小值除2,取两个序列之一贡献这么多,得到子问题

    注意边界情况


    Code:

    #include <cstdio>
    int min(int x,int y){return x<y?x:y;}
    const int N=1000010;
    int n,m,k,a[N],b[N];
    void divide(int la,int ra,int lb,int rb,int nk)
    {
        if(la>ra)
        {
            printf("%d
    ",b[lb+nk-1]);
            return;
        }
        if(lb>rb)
        {
            printf("%d
    ",a[la+nk-1]);
            return;
        }
        if(nk==1)
        {
            printf("%d
    ",min(a[la],b[lb]));
            return;
        }    
        int lk=nk>>1;
        lk=min(lk,min(ra+1-la,rb+1-lb));
        if(a[la+lk-1]<b[lb+lk-1])
            divide(la+lk,ra,lb,rb,nk-lk);
        else
            divide(la,ra,lb+lk,rb,nk-lk);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        for(int i=1;i<=m;i++) scanf("%d",b+i);
        divide(1,n,1,m,k);
        return 0;
    }
    
    

    有序数列第K小加强版

    加上多次区间询问


    Code:

    #include <cstdio>
    int min(int x,int y){return x<y?x:y;}
    const int N=1000010;
    int n,m,q,a[N],b[N];
    void divide(int la,int ra,int lb,int rb,int nk)
    {
        if(la>ra)
        {
            printf("%d
    ",b[lb+nk-1]);
            return;
        }
        if(lb>rb)
        {
            printf("%d
    ",a[la+nk-1]);
            return;
        }
        if(nk==1)
        {
            printf("%d
    ",min(a[la],b[lb]));
            return;
        }
        int lk=nk>>1;
        lk=min(lk,min(ra+1-la,rb+1-lb));
        if(a[la+lk-1]<b[lb+lk-1])
            divide(la+lk,ra,lb,rb,nk-lk);
        else
            divide(la,ra,lb+lk,rb,nk-lk);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        for(int i=1;i<=m;i++) scanf("%d",b+i);
        scanf("%d",&q);
        int l1,l2,r1,r2,k;
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d%d%d%d",&l1,&r1,&l2,&r2,&k);
            divide(l1,r1,l2,r2,k);
        }
        return 0;
    }
    

    2018.7.26

  • 相关阅读:
    从零开始设计一套指令集及其虚拟机
    一种高效整数开平方算法:逐比特确认法
    C 可变参数函数的本质
    C 基础数据类型 性能测试
    用C在GBA上写光线追踪(0)配置开发编译环境
    用C#写小工具:将圆柱面贴图映射到半球贴图
    Linux 硬盘UUID相同处理方法
    ELK6.x_Kafka 安装配置文档
    Nagios4.x安装配置总结
    Cacti-0.8.8b详细安装及配置步骤
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9369973.html
Copyright © 2011-2022 走看看