当前位置: 首页 > news >正文

UVa714 Copying Books(二分答案+贪心)

题目链接
在这里插入图片描述
1.题目大意:把一个正整数序列划分成k个非空的连续子序列,使得每个正整数恰好属于一个序列。设第i个序列的各数之和为S(i),现在我们要让所有S(i)的最大值尽量小。而且如果有多个解,S(1)尽量小,在此前提下S(2)尽量小…,按要求输出

2.最大值尽量小显然是需要二分答案。对于当前得到的答案,我们只需贪心的一直向后选择最大的子区间,即这一段相加小于等于当前答案。如果整个序列划分的个数小于等于k-1,那么当前答案符合要求,继续划分更小的区间,直到得到最后的答案

3.题目要求前面的尽量小,那么,我们就保证后面的尽量大,每次将后面选择到不能大于当前答案为止。但是这样又会导致可能被划分的区间小于k,根据题意就是按前面如果一个数字后面没有区间,就直接插入’/’

4.因为后面我们要从后选择插入’/’,那么我们一开始检查的时候也必须从后面开始检查,这样并不影响最后的划分,因为从前向后划分和从后向前划分都是正确的

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
ll a[505];
int n,k;
bool v[505];

bool check(ll val){
    int cnt=1;
    ll sum=0;
    for(int i=n;i>=1;i--){
        if(sum+a[i]<=val)
            sum+=a[i];
        else{
            cnt++;
            sum=a[i];
        }
        if(cnt>k) return 0;
    }
    return 1;
}

void solve(int val){
    ll sum=0;
    int cnt=0;
    memset(v,0,sizeof v);
    for(int i=n;i>=1;i--){
        if(sum+a[i]<=val){
            sum+=a[i];
        }else{
            v[i]=1; //当前数不能再加入此序列,因此代表后面有一个'/'
            cnt++;
            sum=a[i];
        }
    }
    int x=k-cnt-1,p=1;  //记录还有几个'/'没有插入
    //cout<<x<<endl;
    while(x>0 && p<=n){  //贪心从前插入
        if(!v[p]){ 
            v[p]=1;
            x--;
        }
        p++;
    }
    int flag=1;
    for(int i=1;i<=n;i++){  //输出
        if(flag){
            if(!v[i]){
                cout<<a[i];
            }else cout<<a[i]<<" /";
            flag=0;
        }else{
            if(!v[i]){
                cout<<" "<<a[i];
            }else cout<<" "<<a[i]<<" /";
        }
    }
    cout<<endl;
}


int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        cin>>n>>k;
        ll l=-1,r=0;  //左边界是所有数的最大值,右边界是所有数的和
        for(int i=1;i<=n;i++){
            cin>>a[i];
            l=max(l,1LL*a[i]);
            r+=a[i];
        }
        ll mid;
        while(l<r){
            mid=(l+r)>>1;
            if(check(mid)){
                r=mid;
            }else l=mid+1;
        }
        //cout<<l<<endl;
        solve(l);
    }
    return 0;
}


相关文章:

  • 《程序员羊皮卷》成为电子工业出版社本周重点推荐图书
  • UVa12627 Erratic Expansion(递归/找规律)
  • 《金牌网管师》——10年的沉淀,18年的积累
  • 2020 CodeJam Round 1A
  • 如何更换Android模拟器界面
  • 2019 ICPC Latin American Regional Contests 计蒜客重现
  • youtube weburl后缀
  • UVa12174 Shuffle(滑动窗口)
  • Android开发指南-工具-画九宫格
  • UVa1608 Non-boring sequences(尺取+分治)
  • 通过枚举窗口获得窗口句柄名字并重命名窗口
  • “Shopee杯” e起来编程暨WHU2020校赛热身赛
  • CSDN BLOG EXPERT
  • Android开发指南-二维图形
  • n的阶乘在m进制下结尾0的个数
  • Angular Elements 及其运作原理
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Django 博客开发教程 16 - 统计文章阅读量
  • gulp 教程
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • LintCode 31. partitionArray 数组划分
  • Map集合、散列表、红黑树介绍
  • React 快速上手 - 07 前端路由 react-router
  • Redis 中的布隆过滤器
  • Spring Boot MyBatis配置多种数据库
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 包装类对象
  • 从0实现一个tiny react(三)生命周期
  • 从PHP迁移至Golang - 基础篇
  • 对JS继承的一点思考
  • 关于 Cirru Editor 存储格式
  • 汉诺塔算法
  • 开年巨制!千人千面回放技术让你“看到”Flutter用户侧问题
  • 力扣(LeetCode)21
  • 前端学习笔记之观察者模式
  • 如何学习JavaEE,项目又该如何做?
  • 设计模式(12)迭代器模式(讲解+应用)
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 我看到的前端
  • 新书推荐|Windows黑客编程技术详解
  • 用element的upload组件实现多图片上传和压缩
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 最简单的无缝轮播
  • #git 撤消对文件的更改
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #Ubuntu(修改root信息)
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • ${factoryList }后面有空格不影响
  • (4)Elastix图像配准:3D图像
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • .NET Core WebAPI中封装Swagger配置
  • .NET delegate 委托 、 Event 事件
  • .net php 通信,flash与asp/php/asp.net通信的方法