对于选的物品,总值一定有在前一段区间递减,后一段递增的性质,那么就可以二分。
check()
时只递归归并大的一段,用nth_element
即可
#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();}