zoukankan      html  css  js  c++  java
  • NOIP 模拟 $34; m Merchant$

    题解 (by;zjvarphi)

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

    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
    ");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
    ");return 0;}
                    if (tmpk<=0) continue;
                    register ll ts=ceil(1.0*(S-tmpb)/tmpk);
                    ans=cmin(ans,ts);
                }
                printf("%lld
    ",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
    ",res);
            }
            return 0;
        }
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    mongoDb学习以及spring管理 (包括百度云配置)
    Python循环嵌套
    Web应用功能测试测试点
    二维数组联通子数组
    二维数组最大子数组问题
    环一维数组最大子数组问题
    电梯调研
    最大子数组问题
    小学生题目
    3.13题目思路
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15121909.html
Copyright © 2011-2022 走看看