【bzoj1044】[HAOI2008]木棍分割 二分+dp
题目描述
有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007。。。
输入
输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,1000),1<=Li<=1000.
输出
输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.
样例输入
3 2
1
1
10
样例输出
10 2
题解
二分+dp
第一问即 noip2015跳石头 。。。一眼二分,然后看不满足条件时就切一刀,判断是否小于m。
第二问求方案数,很显然是个dp。
设$f[i][j]$表示前$i$个分了$j$段的方案数,那么状态转移方程应该为$f[i][j]=\sum\limits_{len(t+1,i)\le ans1}f[t][j-1]$,边界条件$f[0][0]=1$,其中$len(a,b)表示$[a,b]$所有木棍的长度总和。
可以发现$t$的取值范围是一段连续的单调的区间,因此可以用类似双指针的方法扫出$t$的取值左端点。然后$\sum$又可以使用前缀和维护,这样时间复杂度就降为了$O(nm)$。
然而这样还会炸空间。。。
因此使用滚动数组就好了,显然第二维是可以滚动的,因此先枚举第二维,滚动一下就好了。
#include <cstdio>
#include <algorithm>
#define N 50010
#define mod 10007
using namespace std;
int n , m , a[N] , sl[N] , f[2][N] , sum[2][N];
bool judge(int mid)
{
int i , now = 0 , cnt = 0;
for(i = 1 ; i <= n ; i ++ )
{
if(now + a[i] > mid) now = 0 , cnt ++ ;
now += a[i];
}
return cnt <= m;
}
int main()
{
int i , j , l = 0 , r = 0 , mid , ans = -1 , p = 0 , ret = 0 , d;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , l = max(l , a[i]) , r += a[i] , sl[i] = sl[i - 1] + a[i];
while(l <= r)
{
mid = (l + r) >> 1;
if(judge(mid)) ans = mid , r = mid - 1;
else l = mid + 1;
}
printf("%d " , ans);
for(i = 0 ; i <= n ; i ++ ) sum[0][i] = 1;
for(i = d = 1 ; i <= m + 1 ; i ++ , d ^= 1)
{
sum[d][0] = p = 0;
for(j = 1 ; j <= n ; j ++ )
{
while(sl[j] - sl[p] > ans) p ++ ;
f[d][j] = sum[d ^ 1][j - 1];
if(p) f[d][j] = (f[d][j] - sum[d ^ 1][p - 1] + mod) % mod;
sum[d][j] = (sum[d][j - 1] + f[d][j]) % mod;
}
ret = (ret + f[d][n]) % mod;
}
printf("%d\n" , ret);
return 0;
}
【bzoj1044】[HAOI2008]木棍分割 二分+dp的更多相关文章
- bzoj1044: [HAOI2008]木棍分割 二分+dp
有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少 ...
- [BZOJ1044][HAOI2008]木棍分割 二分+贪心+dp+前缀和优化
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4112 Solved: 1577 [Submit][St ...
- Luogu P2511 [HAOI2008]木棍分割 二分+DP
思路:二分+DP 提交:3次 错因:二分写萎了,$cnt$记录段数但没有初始化成$1$,$m$切的次数没有$+1$ 思路: 先二分答案,不提: 然后有个很$naive$的$DP$: 设$f[i][j] ...
- [bzoj1044][HAOI2008][木棍分割] (二分+贪心+dp+队列优化)
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...
- [BZOJ1044][HAOI2008]木棍分割 二分 + 单调队列优化dp + 滚动数组优化dp
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...
- BZOJ1044 [HAOI2008]木棍分割 【二分+Dp】
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4281 Solved: 1644 [Submit][St ...
- BZOJ 1044: [HAOI2008]木棍分割(二分答案 + dp)
第一问可以二分答案,然后贪心来判断. 第二问dp, dp[i][j] = sigma(dp[k][j - 1]) (1 <= k <i, sum[i] - sum[k] <= ans ...
- bzoj1044[HAOI2008]木棍分割 单调队列优化dp
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4314 Solved: 1664[Submit][Stat ...
- BZOJ1044: [HAOI2008]木棍分割
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1580 Solved: 567[Submit][Statu ...
随机推荐
- base64位 解码图片
jar包是commons-codec.jar. pnuts //base64解码成图片 function gldBase64ToImage(imgStr,imgFilePath) { // 对字节数组 ...
- ios统计流量代码
#include <ifaddrs.h> #include <sys/socket.h> #include <net/if.h> 1.3G/GPRS流量统计 int ...
- Hibernate基础学习2
Hibernate基础学习2 测试hibernate的一级缓存,事务以及查询语句 1)Hibernate的一些相关概念 hibernate的一级缓存 1)缓存是为了提高该框架对数据库的查询速度 2)一 ...
- input属性总结
<input type="text" readonly="readonly" /> 这个是不能输入的 readonly="readonly ...
- 转 Ubuntu 下 vim 搭建python 环境 配置
1. 安装完整的vim# apt-get install vim-gnome 2. 安装ctags,ctags用于支持taglist,必需!# apt-get install ctags 3. 安装t ...
- windows下的node.js和npm的安装步骤详解
一.使用之前,我们先来掌握3个东西是用来干什么的. npm: Nodejs下的包管理器. webpack: 它主要的用途是通过CommonJS的语法把所有浏览器端需要发布的静态资源做相应的准备,比如资 ...
- arm-none-linux-gnueabi-gcc No such file or directory这个错误的解决方法
这个gcc可执行文件是32位的版本,而在64位系统上需要安装32位兼容包才可以运行正常 .用file命令查看这个文件得到: 解决办法: 安装ia32-libs sudo apt-get install ...
- 【转载】CentOS7.0下安装Telnet
1..先检查CentOS7.0是否已经安装以下两个安装包:telnet-server.xinetd.命令如下: # rpm -qa telnet-server # rpm -qa xinetd 如果没 ...
- LeetCode summary
https://www.programcreek.com/2013/08/leetcode-problem-classification/ https://medium.com/algorithms- ...
- c++ tie,ignore
ignore 一个未指定的类型对象,任何值都可以没有影响地赋值给它.通常使用tie来解压一个元组,作为可以忽略的占位符. #include <iostream> #include < ...