2014.9.6模拟赛【工资】

1.    工资

(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//

“//”表示老大要去拿钱。

 

同bzoj1639……二分

我的r才开10w,结果只有70……

#include<cstdio>
int n,m,l,r,ans;
int a[100010];
int s[100010];
inline int max(int a,int b)
{return a>b?a:b;}
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline bool jud(int k)
{
    int sum,piece=m-1,now=1;
    while (piece&&now<=n)
    {
        sum=0;
        while (now<=n&&sum+a[now]<=k) sum+=a[now++];
        piece--;
    }
    if (now<=n&&s[n]-s[now-1]>k) return 0;
    return 1;
}
int main()
{
	freopen("money.in","r",stdin);
	freopen("money.out","w",stdout);
    n=read();m=read();
    for (int i=1;i<=n;i++)
    {
      a[i]=read();
      s[i]=s[i-1]+a[i];
      l=max(l,a[i]);
    }
    r=10000000;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        if (jud(mid)){ans=mid;r=mid-1;}
        else l=mid+1;
    }
    printf("%d
",ans);
}

  

——by zhber,转载请注明来源
原文地址:https://www.cnblogs.com/zhber/p/4036004.html