• bzoj3874 宅男计划 三分 贪心


    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3874

    题意:有许多种食品,每种有价格、保质期两种属性,一个人有一个数目的钱,求这个人可以活多久。

    如果数据范围小一点那这个显然可以$DP$……然而$0<=Si<=(10^{18}),1<=F,Pi,M<=(10^{18}),1<=N<=200$……我也很绝望啊……

    首先这个东西是个凸函数(为什么?我不知道联想生活实际),也就是存活天数是与送餐次数成凸函数(其实不是严格单峰,但在本题可以忽略),那么我们显然可以三分求出最大函数值。

    问题变为给出一个$x$,如何求出一个$y$。

    根据贪心原则,保质期短价格贵的直接扔掉,于是我们先预处理一下,预处理完之后我们就挨个购买,考虑这个东西每次可以购买的数量。注意最后可能还剩下一些钱够买几次但是不足够每次都买,这一部分也要加以考虑。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn=205;
     7 struct food
     8 {
     9     long long p,s;
    10 }fin[maxn],sta[maxn];
    11 inline bool comp(const food &x,const food &y)
    12 {
    13     if(x.s!=y.s)return x.s<y.s;
    14     return x.p<y.p;
    15 }
    16 inline bool cmp(const food &x,const food &y)
    17 {
    18     return x.p<y.p;
    19 }
    20 long long m,f;int p,n;
    21 inline long long F(long long val)
    22 {
    23     long long tmp=m-f*val,day=0,ans=0;
    24     if(tmp<0)return 0;
    25     for(int i=1;i<=p;i++)
    26     {
    27         if(fin[i].s>=day)
    28         {
    29             long long con=fin[i].s-day+1ll;
    30             long long liv=min(con,tmp/(fin[i].p*val));
    31             ans+=liv*val;day+=liv;tmp-=fin[i].p*val*liv;
    32         }
    33         if(fin[i].s>=day)
    34         {
    35             long long liv=min(val,tmp/fin[i].p);
    36             ans+=liv;day++;tmp-=fin[i].p*liv;
    37         }
    38     }
    39     return ans;
    40 }
    41 int haha()
    42 {
    43     scanf("%lld%lld%d",&m,&f,&n);
    44     for(int i=1;i<=n;i++)scanf("%lld%lld",&sta[i].p,&sta[i].s);
    45     sort(sta+1,sta+n+1,comp);p++,fin[p]=sta[1];
    46     for(int i=1;i<=n;i++)
    47         if(fin[p].s<sta[i].s)p++,fin[p]=sta[i];
    48     sort(fin+1,fin+p+1,cmp);
    49     long long l=1,r=m/(f+fin[1].p);
    50     long long ans=max(F(l),F(r));
    51     while(r-l>=10)
    52     {
    53         long long mid1=l+(r-l+1)/3,mid2=r-(r-l+1)/3;
    54         if(F(mid1)<F(mid2))l=mid1,ans=max(ans,F(mid1));
    55         else r=mid2,ans=max(ans,F(mid2));
    56     }
    57     for(long long i=l;i<=r;i++)ans=max(ans,F(i));
    58     printf("%lld
    ",ans);
    59 }
    60 int sb=haha();
    61 int main(){;}
    bzoj3874
  • 相关阅读:
    F广搜
    Python中range和xrange的异同之处
    数组中出现次数超过一半的数字
    iOS开发之剖析&quot;秘密&quot;App内容页面效果(一)
    Balloon Comes!
    scikit-learn: isotonic regression(保序回归,非常有意思,仅做知识点了解,但差点儿没用到过)
    C#数据缓存介绍及Caching通用帮助类整理
    SVN Working copying &#39;xxxxx/xxxx/xxxx&#39; locked
    读书笔记-APUE第三版-(7)进程环境
    UVA 10555
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7623373.html
Copyright © 2020-2023  润新知