题目描述

有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连
接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长
度最大的一段长度最小. 并将结果mod 10007。。。

输入

输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,10
00),1<=Li<=1000.

输出

输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.

样例输入

3 2
1
1
10

样例输出

10 2

提示

两种砍的方法: (1)(1)(10)和(1 1)(10)

题解 

    人生第一道二分答案成就感满满!二分答案,是指在最小值和最大值之间二分枚举答案,逐渐把答案缩小到一个值得出最优解。二分答案的题目设问常常是最大值最小、最小值最大,解的可能性应该是单调的(即某值不可行则答案只能比它大或只能比它小),需要能简单地验证答案正确与否,要注意的就是防止死循环(不过这道题好像没有这个问题)。对于木棍分割,如果这个值可行,最优解可能比它更小,以它为上界看一看有没有更小的解;如果这个值不可行,只能舍弃它和比它更小的解,以它+1为下界搜索答案。
int check(long long x)
{
temp=he=0;
for(int i=1;i<=n;i++)
{
if(he+li[i]<=x)
he+=li[i];
else
{
he=li[i];
temp++;
if(temp>m)
return 0;
}
}
if(temp>m) return 0;
return 1;
}
le=yd,jg=zd;(最小解是单段木块长度的最大值,最大解是所有木块长度之和)
while(le<jg)
{
mid=(le+jg)>>1;
if(check(mid)) jg=mid;
else le=mid+1;
}
dp部分优化空间复杂度用滚动数组,优化时间复杂度用类似单调队列的思路,和Watching firework is fun大同小异,最后结果为f[i][n]之和。f[i][j]表示j段木块切i次的方案,f[i][j]为所有满足sum[i]-sum[k]<=jg的f[k][j-1]之和(1<=k<i)。f[i]只与f[i-1]有关,第一维只有0和1;sum是单调的,只要维护一个f[k][j-1]之和每次从后部加上新值,从头部减去不满足条件的k对应的值即可。 UPD:关于这个二分卡死的问题后来慢慢弄清了是怎么回事。并不是+1或不+1就容易被卡死,而是你要保证每次l和r总有一个是变化的。比如说mid=l+r>>1,那mid可能和l相等,你就不能if(……)l=mid,如果必须这样就得mid=(l+r+1)>>1。OI中的很多东西开始不明白,用了很长时间忽然就搞懂了,只有看清了内部的原理才是真正的通透啊。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int sj=;
int li[sj],mod=,yd;
int la,no,head,n,m,mid,temp,tail;
long long s[sj],f[][sj],zd,jg,le,he,fas;
int dbj(int x,int y)
{
return x>y?x:y;
}
int xbj(int x,int y)
{
return x<y?x:y;
}
void init()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&li[i]);
s[i]=s[i-]+li[i];
zd+=li[i];
yd=dbj(li[i],yd);
}
}
void dp()
{
for(int i=;i<=n;i++)
{
if(s[i]<=jg)
f[][i]=;
if(s[i]>jg)
break;
}
fas=f[][n];
for(int j=;j<=m;j++)
{
head=;
tail=;
he=;
la=(j+)%;
no=j%;
for(int i=;i<=n;i++)
{
if(i<j) continue;
for(int k=tail+;k<i;k++)
he+=f[la][k];
tail=i-;
while(s[i]-s[head]>jg)
{
he-=f[la][head];
head++;
}
f[no][i]=he;
f[no][i]%=mod;
}
fas+=f[no][n];
fas%=mod;
}
}
int check(long long x)
{
temp=he=;
for(int i=;i<=n;i++)
{
if(he+li[i]<=x)
he+=li[i];
else
{
he=li[i];
temp++;
if(temp>m)
return ;
}
}
if(temp>m) return ;
return ;
}
int main()
{
init();
le=yd,jg=zd;
while(le<jg)
{
mid=(le+jg)>>;
if(check(mid)) jg=mid;
else le=mid+;
}
printf("%lld\n",jg);
dp();
printf("%lld",fas);
//while(1);
return ;
}

木棍分割[HAOI2008]的更多相关文章

  1. 【BZOJ】【1044】【HAOI2008】木棍分割

    二分/DP 真是一道好题! 第一问很简单的二分…… 第二问一开始我想成贪心了,其实应该是DP的= = 然后没有注意……又MLE又TLE的……这题要对DP进行时空两方面的优化!! 题解:(by JoeF ...

  2. BZOJ1044: [HAOI2008]木棍分割

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1580  Solved: 567[Submit][Statu ...

  3. BZOJ 1044: [HAOI2008]木棍分割(二分答案 + dp)

    第一问可以二分答案,然后贪心来判断. 第二问dp, dp[i][j] = sigma(dp[k][j - 1]) (1 <= k <i, sum[i] - sum[k] <= ans ...

  4. bzoj1044[HAOI2008]木棍分割 单调队列优化dp

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4314  Solved: 1664[Submit][Stat ...

  5. 【BZOJ1044】[HAOI2008]木棍分割(动态规划,贪心)

    [BZOJ1044][HAOI2008]木棍分割(动态规划,贪心) 题面 BZOJ 洛谷 题解 第一问随便二分一下就好了,贪心\(check\)正确性显然. 第二问随便前缀和+单调队列优化一下\(dp ...

  6. 【BZOJ1044】[HAOI2008]木棍分割

    [BZOJ1044][HAOI2008]木棍分割 题面 bzoj 洛谷 题解 第一问显然可以二分出来的. 第二问: 设\(dp[i][j]\)表示前\(i\)个,切了\(j\)组的方案数 发现每次转移 ...

  7. 1044: [HAOI2008]木棍分割

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2161  Solved: 779[Submit][Statu ...

  8. BZOJ1044 [HAOI2008]木棍分割 【二分+Dp】

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4281  Solved: 1644 [Submit][St ...

  9. [BZOJ1044][HAOI2008]木棍分割 二分+贪心+dp+前缀和优化

    1044: [HAOI2008]木棍分割 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4112  Solved: 1577 [Submit][St ...

随机推荐

  1. Linq用法笔记

    一.什么是Linq? LINQ即Language Integrated Query(语言集成查询),LINQ是集成到C#和Visual Basic.NET这些语言中用于提供查询数据能力的一个新特性. ...

  2. SSH连接不上CentOS 主机配置文件导致的原因的解决方法

    一.CentOS之SSH的安装与配置 SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定SSH 为建立在应用层和传输层基础上 ...

  3. 限制input[type=number]的输入位数策略整理

    当我们使用类型number的input输入框的时候,我们可能需要限制输入的位数,这个时候通常会想到maxlength,但是maxlength是在number类型的时候是不支持的,下面是一些解决这种问题 ...

  4. 中奖概率算法(php 可用于刮刮卡,大转盘等抽奖算法)

    <?php //中奖概率算法(php 可用于刮刮卡,大转盘等抽奖算法) /* * 经典的概率算法, * $proArr是一个预先设置的数组, * 假设数组为:array(100,200,300, ...

  5. Web前端总结(小伙伴的)

    以下总结是我工作室的小伙伴的心得,可以参考一下 html+css知识点总结 HTMl+CSS知识点收集 1.letter-spacing和word-spacing的区别 letter-spacing: ...

  6. Spring Boot1.5.4 连接池 和 事务

    原文:https://github.com/x113773/testall/issues/10 默认连接池---spring Boot中默认支持的连接池有Tomcat.HikariCP .DBCP . ...

  7. 探索Windows命令行系列(7):通过命令编译C#类和Java类

    1.编译 C# 类 1.1.C# 编译工具 1.2.编译一个 C# 类 1.3.编译多个 C# 类 2.编译 Java 类 2.1.Java 编译工具 2.2.编译 Java 类 3.组合命令符 4. ...

  8. Maven pom.xml配置详解

    POM的全称是“ProjectObjectModel(项目对象模型)”. 声明规范 <projectxmlns="http://maven.apache.org/POM/4.0.0&q ...

  9. App 组件化/模块化之路——构建开发架构思路

    App 组件化/模块化开发架构思路 随着业务的发展 App 开发技术也越来越成熟,对开发者来说 App 代码量也迅速地增长到一个数量级.对于如何架构 App 已经每个开发者面临的实际问题.好的架构可以 ...

  10. Linux 密钥验证

    服务端配置puttygen 生成公钥,保存私钥复制公钥,写入服务端mkdir /root/.sshvi /root/.ssh/authorized_keys 生成文件,将公钥写入到文件中chmod 7 ...