(money/money.in/money.out) 时限1000ms 内存256MB 聪哥在暑假参加了打零工的活动,这个活动分为n个工作日,每个工作日的工资为Vi。有m个结算工钱的时间,聪哥可以自由安排这些时间,也就是说什么时候拿钱,老板说的不算,聪哥才有发言权!(因为聪哥是土豪,他是老板的老板) 聪哥不喜欢身上一次性有太多的钱,于是他想安排一下拿钱的时间,使他一次性拿的钱中最大的最小。(最后一天一定要领钱) 输入 第一行 2个数 n,m 接下来n行,每行一个数,代表Vi. 输出 最小的最大钱数。 样例输入 7 5 100 400 300 100 500 101 400 样例输出 500 样例说明 100 400//300 100//500//101//400// “//”表示老大要去拿钱。 数据范围 20% 1<=n<=20 另 20% 1<=n<=50,Vi的和不超过1000 100% 1<=n<=100,000,m<=n,Vi<=10,000
明显,二分答案,是的最大的区间段和最小
还有一个限制条件,最后一天必须结算
判断的时候加以分析就好了
分值:100/100
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<string> 5 #include<cstdio> 6 #include<queue> 7 #include<cmath> 8 #define ll long long 9 #define DB double 10 using namespace std; 11 inline int read() 12 { 13 int x=0,w=1;char ch=getchar(); 14 while(!isdigit(ch)){if(ch=='-') w=-1;ch=getchar();} 15 while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); 16 return x*w; 17 } 18 const int N=1e5+100; 19 int n,m,a[N],M; 20 ll ans,L,R,mid,k; 21 bool v[N]; 22 bool ok(ll x) 23 { 24 M=0;k=0;v[n]=0; 25 for(int i=1;i<=n;++i) 26 { 27 if(x<a[i]) return 0; 28 k+=a[i]; 29 if(k>x) M++,k=a[i],v[i-1]=1; 30 // cout<<k<<" "<<M<<" "<<i<<endl; 31 if(M>m) return 0; 32 } 33 if(k>x) return 0; 34 // cout<<k<<" "<<v[n]<<endl; 35 if(!v[n]){v[n]=1;M++;} 36 if(M<=m) return 1; 37 return 0; 38 } 39 int main() 40 { 41 freopen("money.in","r",stdin); 42 freopen("money.out","w",stdout); 43 n=read();m=read(); 44 for(int i=1;i<=n;++i) a[i]=read(),R+=a[i]; 45 // cout<<ok(38); 46 while(L<=R) 47 { 48 mid=(L+R)>>1; 49 if(ok(mid)) ans=mid,R=mid-1; 50 else L=mid+1; 51 } 52 printf("%lld",ans); 53 return 0; 54 }