bzoj 4590 自动刷题机 Posted on 2019-06-10 | Views: 二分答案. 不难发现 $n$ 增大,切题数不会增多, $n$ 减小,切题数不会减少. 于是分别二分 $n$ 的最小值与最大值,检验直接模拟操作就好了. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687#include<bits/stdc++.h>using namespace std;typedef long long ll;inline int read(){ int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh;}const int MAXN=1e5+10;int n,k,x[MAXN];bool checkmin(ll mid){ int tot=0; ll len=0; for(int i=1;i<=n;++i) { len+=x[i]; len=max(len,0LL); if(len>=mid) len=0,++tot; } if(len>=mid) len=0,++tot; return tot<=k;}ll solvemin(){ ll L=1,R=1e18; ll ans=-1; while(L<=R) { ll mid=(L+R)>>1; if(checkmin(mid)) ans=mid,R=mid-1; else L=mid+1; } return ans;}bool checkmax(ll mid){ int tot=0; ll len=0; for(int i=1;i<=n;++i) { len+=x[i]; len=max(len,0LL); if(len>=mid) len=0,++tot; } if(len>=mid) len=0,++tot; return tot>=k;}ll solvemax(){ ll L=1,R=1e18; ll ans=-1; while(L<=R) { ll mid=(L+R)>>1; if(checkmax(mid)) ans=mid,L=mid+1; else R=mid-1; } return ans;}int main(){ n=read(),k=read(); for(int i=1;i<=n;++i) x[i]=read(); ll a=solvemin(),b=solvemax(); if(a>b || a<0 || b<0) puts("-1"); else cout<<a<<' '<<b<<endl; return 0;}