UVA714 二分查找答案

题目:一本书要分给n个人打理,问如何分割使的最大值最小,并且要使得前面的人的最小

我的最初做法:
枚举答案,用for循环,再在递归里再去枚举答案。
但是wa了,我还未知原因。

看了网上题解之后
发现它是用二分的,枚举答案,不如用二分缩小答案范围更快,
而对于要使越前面的人分到的越小,它是很取巧的,如果要分n部分,但是只分了n-2,直接从前面往后面分,没有”/“的元素就是直接价格“/”。

总体思路:
猜测答案,验证答案对否(方法是直接看拆的的分数符合要求否),再不停的用二分猜测答案验证答案,最后标记输出。

#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=600;
ll m,n,sum[maxn],all[maxn];
bool is_ok(ll a)
{
    ll now=a;
    int th=0,time=0;
    while(th<=m)
    {
        int k=upper_bound(sum+1,sum+m+1,now)-sum-1;
        time++;
        now=sum[k]+a;
        if(k==m)
        {
            if(time<=n)return 1;
            return 0;
        }
        if(k==th)return 0;
        th=k;
    }
}
ll solve()
{
    ll lef=sum[m]/n,rig=sum[m];
    while(lef<rig)
    {
        ll ans=lef+(rig-lef)/2;
        if(is_ok(ans))rig=ans;
        else lef=ans+1;
    }
    return lef;
}
void print(ll ans)
{
    ll biao[maxn];
    memset(biao,0,sizeof(biao));
    ll tot;
    int time=0;
    for(int i=m;i>=1;)
    {
         tot=0;
        while(tot+all[i]<=ans)
        {
            tot+=all[i--];
        }
        biao[i]=1;
        time++;
    }
    int dt=1;
    while(time!=n)
    {
        if(!biao[dt]){biao[dt]=1;time++;}
        dt++;
    }
    for(int i=1;i<=m;i++)
    {
        printf("%lld%s",all[i],i==m?"\n":" ");
        if(biao[i])printf("/ ");
    }
}
int main(void)
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%lld %lld",&m,&n);
        sum[0]=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%lld",&all[i]);
        sum[i]=sum[i-1]+all[i];
        }
        ll ans=solve();
        print(ans);
}}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是Mally呀!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值