zoukankan      html  css  js  c++  java
  • luogu2678 跳石子 二分

    题目大意:

    一个赛道上除起点、终点外有(N)个点。现要求你从中删除(M)个点,使得剩余点序列中相邻的点的最小值最大。求这个最大的最小值。

    思路

    我们最容易想到的算法便是:对序列从头到尾循环(M)次,每次把间距最小的一对点删除其中一个,删除的那一个点到两边的点的距离之和应当是相对小的那一个。但是代码具体实现怎么做?而且时间复杂度也太高了!此时我们应当直接换切入点,而不是想方设法在这个思路上寻找解决方法。
    题中要我们求的是,而值的范围由起点和终点不改变已经是有限了。而且显然要求的这个最小值越大,要删去的点不变或越多,否则不变越少。于是我们就可以对要求的最大的最小值进行UpperBound二分了。
    那么对于一个潜在的值mid,如何得知要想使剩余点序列中相邻的点的最小值至少为(m)要删去多少个点呢?问题就在于,如果我们知道一对相邻点距离小于mid,我们是删除左面的点还是右面的点。贪心告诉我们删除右面的点,因为删除右边的点r会影响到更右边的点r',它若不删去r则它与相邻的点的距离小于mid,那么它更可能不用删去它本身而满足条件,而删除左面的点达不到这样的效果。

    //#define _DEBUG//DELETE!!!!!!!!!!!!!!!
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int MAX_P = 50010;
    int P[MAX_P];
    int N, M, L;
    
    bool CanDelInM(int x)
    {
        int lastPos = 0, cnt = 0;
        for(int i=1; i<=N+1; i++)
        {
            if(P[i] - lastPos < x)
                cnt++;
            else
                lastPos = P[i];
        }
        return cnt <= M;
    }
    
    
    int UpperBound(int l, int r, bool (*GreaterOrEqual)(int))
    {
        while(r > l)
        {
            int mid = (l + r + 1) / 2;
            if(GreaterOrEqual(mid))
                l = mid;
            else
                r = mid - 1;
        }
        return l;
    }
    
    int main()
    {
        scanf("%d%d%d", &L, &N, &M);
        for(int i=1; i<=N; i++)
            scanf("%d", P + i);
        P[N+1]=L;
        sort(P+1, P+N+1);
        printf("%d
    ", UpperBound(1, L, CanDelInM));
        return 0;
    }
    
    
  • 相关阅读:
    mojo 接口示例
    MojoliciousLite: 实时的web框架 概述
    接口返回json
    centos 6.7 perl 版本 This is perl 5, version 22 安装DBI DBD
    centos 6.7 perl 5.22 安装DBD 需要使用老的perl版本
    商业智能改变汽车行业
    商业智能改变汽车行业
    读MBA经历回顾(上)目的决定手段——北漂18年(48)
    perl 升级到5.20版本
    Group Commit of Binary Log
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9094533.html
Copyright © 2011-2022 走看看