zoukankan      html  css  js  c++  java
  • Gym 101510C

    题意略。

    思路:

    由于xi的选取是任意的,所以我们不用去理会题目中的xi数列条件。主要是把关注点放在长度为L的线段覆盖至少k个整数这个条件上。

    像这种取到最小的合法解的问题,我们应该要想到使用二分法来试探。

    那么在验证时,如果我们要验证下标为i的的这个项是否能被一个包含k个元素的区间覆盖,就要枚举这个区间左边端点 <= i 并且 右边端点 >= i的所有情况,

    在这些情况中,只要存在一个合法的解,那么该项就可以找到一个合法的xi。

    如果我们对于每一个项都这么验证,那么我们的时间复杂度无法承受。

    我们发现,如果当前区间已经包含了 i 和 i + 1 ,那么如果对于i来说,这个区间的r - l + 1 <= L,那么对于i + 1来说,该区间也是合法的。

    也就是说,我们可以利用上前面的结果,当需要的时候,我们才去移动这个验证区间。

    如果当前区间的长度大于L,那么我们也需要右移这个区间,直到找到一个合法的区间,如果在包含 i 的前提下,该区间不存在,

    那么说明这个L不行。

    详见代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 200005;
    
    LL store[maxn],minn,maxx;
    int n,k;
    
    bool jud(LL x)
    {
          int l,r;
          bool ret = true;
          l = 0,r = k - 1;
          for (int i = 0;i < n;++i)
          {
            while ((store[r] - store[l] > x && l < i && r < n - 1) || r < i){
                ++l,++r;
            }
               if (store[r] - store[l] > x)
               {
                ret = false;
                  break;
            }
          }
          return ret; 
    }
    
    int main(){
        scanf("%d%d",&n,&k);
        scanf("%lld",&store[0]);
        minn = maxx = store[0];
        for(int i = 1;i < n;++i){
            scanf("%lld",&store[i]);
            minn = min(minn,store[i]);
            maxx = max(maxx,store[i]);
        }
        sort(store,store + n);
        LL l = 0,r = maxx - minn;
        while(l < r){
            LL mid = (l + r)>>1;
            if(jud(mid)) r = mid;
            else l = mid + 1;
            //printf("mid == %lld
    ",mid);
        }
        printf("%lld
    ",l);
        return 0;
    }
  • 相关阅读:
    C# 窗体WinForm中动态显示radioButton实例
    C#和Java交互相关研究
    c# 注册表操作,创建,删除,修改,判断节点是否存在
    C#单例模式的三种写法
    C#中使用TCP通信
    c#中this的用法
    C#单例模式的三种写法
    二十道经典C#面试题
    Linux chattr 命令详解
    Linux ulimit命令详解
  • 原文地址:https://www.cnblogs.com/tiberius/p/9301538.html
Copyright © 2011-2022 走看看