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

  • 相关阅读:
    oracle表解锁
    pl/sql 如何配置连接远程一个或多个数据库
    Hibernate通过自编写Sql修改
    Hibernate通过自编写sql查询
    java生成临时令牌和访问令牌
    java生成字母首位8位随机码
    [C] 创建目录_mkdir()函数
    [C] 判断目录 / 文件是否存在access()函数
    [C] getopt使用说明
    [C] Segmentation fault (core dumped)
  • 原文地址:https://www.cnblogs.com/smartljy/p/13468470.html
Copyright © 2011-2022 走看看