zoukankan      html  css  js  c++  java
  • 借书【二分】

    借书【二分】

    题目描述

    DilhaoDilhao一共有nn本教科书,每本教科书都有一个难度值,他每次出题的时候都会从其中挑两本教科书作为借鉴,如果这两本书的难度相差越大,DilhaoDilhao出的题就会越复杂,也就是说,一道题的复杂程度等于两本书难度差的绝对值。

    这次轮到ldxxxldxxx出题啦,他想要管DilhaoDilhao借mm本书作为参考去出题,DilhaoDilhao想知道,如果ldxxxldxxx在DilhaoDilhao给出的mm本书里挑选难度相差最小的两本书出题,那么ldxxxldxxx出的题复杂程度最大是多少?

    输入格式

    第一行是nn和mm。

    接下来的nn行,每行一个整数aiai表示第ii本书的难度。

    输入格式

    一个整数为ldxxxldxxx出的题复杂程度的最大值。

    输入样例

    6 3

    5

    7

    1

    17

    13

    10

    输出样例

    7

    样例解释

    DilhaoDilhao给了ldxxxldxxx难度为1,10,171,10,17的三本书,ldxxxldxxx挑选难度为1010和1717的两本书,出题复杂度为77;

    如果DilhaoDilhao给出其他任何三本书,其中的两本书难度差的最小值都小于77,所以ldxxxldxxx出题最大的复杂程度为77。

    数据说明

    对于 30%30%的数据: 2≤n≤202≤n≤20;

    对于 60%60%的数据: 2≤n≤10002≤n≤1000;

    对于 100%100%的数据: 2≤n≤1000002≤n≤100000, 2≤m≤n2≤m≤n, 0≤ai≤10000000000≤ai≤1000000000。


    思路分析

    • 题目很好理解,一堆书中给你m本书,选出这m本书中两本书难度差最小的值作为出题的复杂程度,最后输出最大复杂程度,显然是一道最小值最大化的问题,就需要用到二分

    二分从哪里入手

    • 首先可以明确的是这题要对差值处理,考虑到我们要选m本中的最小差值,那么我们完全可以将原数组排序后处理为差分数组,然后两个数的差值从前往后加即可
    • 二分过程:
      • 最大的最小差值为边界,然后判断右边界(显然右边界最大)是否成立,成立即为最优答案,否则再判断mid,进行区间缩小
      • 判断条件:我们只需要看以该值作为最小差值是否能选出m个数即可(即m-1个差值)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    inline int read(){
       int s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    const int maxn=1e5+5;
    int n,m,a[maxn],cf[maxn];
    int Max=0;
    void Init(){
    	n = read(),m = read();   
        for(int i=1;i<=n;i++){
            a[i] = read();
            Max=max(Max,a[i]);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<n;i++){
            cf[i]=a[i+1]-a[i];//cf差分数组
        }
    }
    bool check(int x){ //x为二分过程中枚举的差值
        int cnt=0,ch=0;//ch当前的最大差值
        for(int i=1;i<n;i++){
            ch+=cf[i];
            if(ch>=x){//找到一对差值大于x
                cnt++,ch=0;//从下个位置找下一对
            }
        }
        if(cnt>=m-1)return true; //能够找出m-1个差值
        return false;
    }
    int main(){
        n = read(),m = read();   
        for(int i=1;i<=n;i++){
            a[i] = read();
            Max=max(Max,a[i]);
        }
        sort(a+1,a+n+1);
        for(int i=1;i<n;i++){
            cf[i]=a[i+1]-a[i];//cf差分数组
        }
        int l=0,r=Max;
    	while(l<=r){
            if(r-l==1){ //区间不能再缩小
                if(check(r)==true) //右边界最大,判断是否可以作为答案
                    l=r;
                break;
            }
            int mid=(l+r)/2;
            if(check(mid)==true) //向右缩小空间,继续寻找更优解
                l=mid;
            else r=mid; //中间值太大,向右缩小区间
        }
        printf("%d
    ",l);//左边界最小,一定符合答案
        return 0;
    }
    

    发量成功减1%

  • 相关阅读:
    nodejs websocket
    [Java] 数组-01 入门
    [Java] 第一,二章 配置, 基础
    [Java] 第四章 异常机制
    [Java] 第三章 面向对象总结
    [Java] 接口-02
    [Java] 接口-01
    [Java] final 关键字
    [Java] 抽象类
    [Java] 多态-01
  • 原文地址:https://www.cnblogs.com/hhhhalo/p/13251356.html
Copyright © 2011-2022 走看看