Loading

NOIP 模拟 $34\; \rm Merchant$

题解 \(by\;zj\varphi\)

对于选的物品,总值一定有在前一段区间递减,后一段递增的性质,那么就可以二分。

check()时只递归归并大的一段,用nth_element即可

Code
#include<bits/stdc++.h>
#define ri register signed
#define p(i) ++i
namespace IO{
    char buf[1<<21],*p1=buf,*p2=buf;
    #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
    struct nanfeng_stream{
        template<typename T>inline nanfeng_stream operator>>(T &x) {
            ri f=0;x=0;register char ch=gc();
            while(!isdigit(ch)) f|=ch=='-',ch=gc();
            while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
            return x=f?-x:x,*this;
        }
    }cin;
}
using IO::cin;
namespace nanfeng{
    #define FI FILE *IN
    #define FO FILE *OUT
    template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
    template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
    typedef long long ll;
    static const int N=1e6+7;
    int k[N],b[N],n,m;
    ll st[N],S,ans=1e18;
    bool fg1=1,fg2=1;
    inline bool check(register ll mid) {
        register ll sum(0);
        for (ri i(1);i<=n;p(i)) st[i]=k[i]*mid+b[i];
        std::nth_element(st+1,st+n-m,st+n+1);
        for (ri i(n-m+1);i<=n;p(i)) {
            if (st[i]<=0) continue;
            sum+=st[i];
            if (sum>=S) return 1;
        }
        return 0;
    }
    inline int main() {
        //FI=freopen("nanfeng.in","r",stdin);
        //FO=freopen("tst.out","w",stdout);
        cin >> n >> m >> S;
        for (ri i(1);i<=n;p(i)) {
            cin >> k[i] >> b[i];
            if (k[i]>=0) fg2=0;
            else if (k[i]<0) fg1=0;
        }
        if (n<=22) {
            ri s=(1<<n)-1;
            if (!S) {printf("0\n");return 0;}
            for (ri i(1);i<=s;p(i)) {
                register ll tmpk(0),tmpb(0);
                ri nm(0);
                for (ri j(0);j<n;p(j)) if ((i>>j)&1) tmpk+=k[j+1],tmpb+=b[j+1],p(nm);
                if (nm>m) continue;
                if (tmpb>=S) {printf("0\n");return 0;}
                if (tmpk<=0) continue;
                register ll ts=ceil(1.0*(S-tmpb)/tmpk);
                ans=cmin(ans,ts);
            }
            printf("%lld\n",ans);
        } else if (fg2) puts("0");
        else {
            ri l(0),r(1e9),res;
            while(l<=r) {
                ri mid(l+r>>1);
                if (check(mid)) res=mid,r=mid-1;
                else l=mid+1;
            }
            printf("%d\n",res);
        }
        return 0;
    }
}
int main() {return nanfeng::main();}
posted @ 2021-08-10 06:11  ナンカエデ  阅读(37)  评论(0编辑  收藏  举报