zoukankan      html  css  js  c++  java
  • YbtOj练习:二分2 最小时间

    http://noip.ybtoj.com.cn/contest/15/problem/2

    这道题写了快一个早上   卑微

    因为通过其他量来确定时间太难,所以我们可以先确定时间,在来判定该方案是否合法。即答案转化为二分判定。

    对于每一种确定的选法,它的收益都是一个一次函数,要么单调递增要么单调递减。若单调递减,只要t=0可行就可行,若此时不行就一定不行(答案保证有解),而单调递增时,我们需要二分找到最早的符合要求的时刻。因此,对于每一个确定的时间,我们只需要先判定0是否是最优解,若不是再进行二分,二分时每次让答案累加前m大的value即可(小于零的数不要加!!记得判定!!)

    而这时就出现了新的问题,如果每一次都重新排序的话,会TLE。  而实际上我们需要的并不是一个有序的数组,我们只需要前m大的数字就行,因此就可以用nth_element函数来实现(我上一篇博客写了)

    代码如下

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    int n,m,l,r=1e9;
    ll S;
    struct node{
        int k,b;
        ll val;
        bool operator < (const node &G) const
        {
            return val>G.val;
        }
    }a[N];
    bool check(int x)
    {
        for(int i=0;i<n;i++) a[i].val=a[i].k*x+a[i].b;
        ll res=0ll;
        nth_element(a,a+m,a+n);
        for(int i=0;i<m;i++) 
        {
            if(a[i].val>0)  //一开始忘了写,卡了半天!! 
            res+=a[i].val;
            if(res>=S) return true;
        }
        return false;
    }
    signed main()
    {
        scanf("%lld%lld%lld",&n,&m,&S);
        for(int i=0;i<n;i++) scanf("%lld%lld",&a[i].k,&a[i].b);
        if(check(0))
        {
            printf("0");
            return 0;
        }
        while(l<r)
        {
            int mid=l+r>>1;
            if(!check(mid)) l=mid+1;
            else r=mid;
        }
        printf("%lld",l);
        return 0;
    }

     注意这道题要开long long

  • 相关阅读:
    多色图标字体
    css编写规则BEM
    css处理工具PostCss
    vue2.0点击其他任何地方隐藏dom
    vue2.0多页面开发
    Dijkstra算法(邻接矩阵存储)
    kmp算法c++代码实现
    最小生成树(prim算法,Kruskal算法)c++实现
    字符串匹配的KMP算法(转)
    筛选法求素数
  • 原文地址:https://www.cnblogs.com/smartljy/p/13468470.html
Copyright © 2011-2022 走看看