首页 > 技术文章 > Luogu P4040 [AHOI2014/JSOI2014]宅男计划

cjoierShiina-Mashiro 2019-09-26 21:09 原文

题目
显然存活天数与叫外卖次数的函数是凸函数。
所以三分买外卖的次数。
然后把食品按保质期升序排序。
并且单调栈搞一下,把又贵又保质期短的丢掉。
那么随着保质期的增加,食品的价格一定上涨。
所以我们从前往后买,能买多少买对少。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=207;
LL m,f;int n,top;
struct node{LL v,t;}a[N],b[N];
int operator<(node a,node b){return a.t<b.t;}
LL read(){LL x;scanf("%lld",&x);return x;}
LL cal(LL x)
{
    LL res=m-x*f,now=0,t,s=0;
    if(res<0) return 0;
    for(int i=1;i<=top;++i)
    {
	t=min(b[i].t-now,res/(b[i].v*x)),now+=t,s+=t*x,res-=b[i].v*t*x;
	if(now<b[i].t) {s+=res/b[i].v;break;}
    }
    return s;
}
int main()
{
    m=read(),f=read(),n=read();int i;LL l=1,r=m/f,m1,m2,x,s1,s2,ans=0;
    for(i=1;i<=n;++i) a[i]=(node){read(),read()+1};
    sort(a+1,a+n+1);
    for(i=1;i<=n;b[++top]=a[i],++i) while(top&&a[i].v<=b[top].v) --top;
    while(l<=r) x=r-l+1,m1=l+x/3,m2=l+x*2/3,s1=cal(m1),s2=cal(m2),ans=max(ans,(s1<s2? l=m1+1,s2:r=m2-1,s1));
    return !printf("%lld",ans);
}

推荐阅读