P9124 [USACO23FEB] Bakery S 题解

· · 题解

题目传送门 | 珂能更好的食用体验

题意概述

解题思路

我们可以先假设对于第 i 个朋友(订单),需要升级 xA 烤箱, yB 烤箱。

于是,显而易见的:(看起来很简洁但一点都不好解)

a_i \times (t_c-x) + b_i \times (t_m-y) \leqslant c_i

mid=x+y,于是:

a_i \times t_c-a_i \times x+b_i \times t_m - b_i \times mid+b_i \times x \leqslant c_i \therefore (b_i-a_i)\times x \leqslant c_i-a_i \times t_c-b_i\times t_m+b_i\times mid

k_i=c_i-a_i \times t_c-b_i\times t_m+b_i\times mid

所以,就可以根据上述不等式进行二分答案了。(二分的当然是 x+y。)

接下来,浅浅说一下不等式的解集:

\begin{cases}x=\varnothing, &b_i-a_i=0 \\ x\leqslant \dfrac{k_i}{b_i-a_i} , &b_i-a_i>0\\ x\geqslant \dfrac{k_i}{b_i-a_i} , &b_i-a_i<0\end{cases}

上述第 2 个式子用于锁定解集的上限,第 3 个式子用于锁定解集的下限

同时,xy 的值应该为整数。所以为了便于大家理解程序,解集应该写成下面这个亚子。

\begin{cases}x=\varnothing, &b_i-a_i=0 \\\\ x\leqslant \left\lfloor\dfrac{k_i}{b_i-a_i}\right\rfloor , &b_i-a_i>0\\\\ x\geqslant \left\lceil\dfrac{k_i}{b_i-a_i}\right\rceil, &b_i-a_i<0\end{cases}

Code

#include<bits/stdc++.h>
using namespace std;
long long T,n,tc,tM,a[110],b[110],c[110];
bool check(long long x)
{
    long long maxx=min(tc-1,x);
    long long minn=max(0LL,x-tM+1);
    for(int i=1; i<=n; i++)
    {
        long long k=c[i]-a[i]*tc-b[i]*tM+b[i]*x;
        if(b[i]-a[i]==0)
        {   
            if(k<0) return false;
        }
        else if(b[i]-a[i]>0) maxx=min(maxx,(long long)floor(k*1.0/(b[i]-a[i])));//二式
        else minn=max(minn,(long long)ceil(k*1.0/(b[i]-a[i])));//三式
    }
    return maxx>=minn;//判断是否有解
}
int main()
{
    for(cin>>T;T;T--)
    {
        cin>>n>>tc>>tM;
        for(int i=1; i<=n; i++)
            cin>>a[i]>>b[i]>>c[i];
        long long l=-1,r=tc+tM-1;
        while(l+1<r)//简单的二分答案
        {
            long long mid=l+r>>1;
            if(check(mid)) r=mid;
            else l=mid;
        }
        cout<<r<<endl;
    }
    return 0;
}