题目描述

有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. 摘记:LoadRunner

    infrastructure 基础结构 Load Testing:性能测试 predicts system behavior and performance exercises your entire ...

  2. jQuery – 鼠标经过(hover)事件的延时处理

    一.关于鼠标hover事件及延时 鼠标经过事件为web页面上非常常见的事件之一.简单的hover可以用CSS :hover伪类实现,复杂点的用js. 一般情况下,我们是不对鼠标hover事件进行延时处 ...

  3. Java常用类String的面试题汇总

    比较两个字符串时使用"=="还是equals()方法? 当然是equals方法."=="测试的是两个对象的引用是否相同,而equals()比较的是两个字符串的值 ...

  4. php中的XML转数组

    /** * 最简单的XML转数组 * @param string $xmlstring XML字符串 * @return array XML数组 */ function simplest_xml_to ...

  5. [leetcode-516-Longest Palindromic Subsequence]

    Given a string s, find the longest palindromic subsequence's length in s. You may assume that the ma ...

  6. C++ 获取文件夹下的所有文件名

    获取文件夹下所有的文件名是常用的功能,今天再一次有这样的需求,所有就在网上查找了很多,并记下以供后用. 原文:http://blog.csdn.NET/cxf7394373/article/detai ...

  7. jq与原生js实现收起展开效果

    jq与原生js实现收起展开效果 (jq需自己加载) <!DOCTYPE html> <html> <head> <meta charset="UTF ...

  8. 【转】Header Only Library的介绍

    什么是Header Only Library Header Only Library把一个库的内容完全写在头文件中,不带任何cpp文件. 这是一个巧合,决不是C++的原始设计. 第一次这么做估计是ST ...

  9. jquery 变量和原生js变量的关系

    其实js 变量和 jquery没什么不一样, 也可以直接 var  hhhh=$("header"); 但是当用到用到hhh时依然要用jquery 的方式,而不能js原生的方式.

  10. vijos1698题解

    题目: 船体的结构是不能随意修改的..那样会破坏整艘船和谐的韵律.. 虽然说.如果沿岸航行的话是不会预见太大的海浪的..但是还要小心保护轨杆和船帆.. 毕竟对于小s这样的单轨帆船...轨杆和船帆如果受 ...