[BZOJ 1044] [HAOI2008] 木棍分割 【二分 + DP】
题目链接:BZOJ 1044
第一问是一个十分显然的二分,贪心Check(),很容易就能求出最小的最大长度 Len 。
第二问求方案总数,使用 DP 求解。
使用前缀和,令 Sum[i] 为前 i 根木棍的长度和。
令 f[i][j] 为前 i 根木棍中切 j 刀,并且满足最长长度不超过 j 的方案数,那么:
状态转移方程: f[i][j] = Σ f[k][j-1] ((1 <= k <= i-1) && (Sum[i] - Sum[k] <= Len))
这样的空间复杂度为 O(nm) ,时间复杂度为 O(n^2 m) 。显然都超出了限制。
下面我们考虑 DP 的优化。
1) 对于空间的优化。
这个比较显然,由于当前的 f[][j] 只与 f[][j-1] 有关,所以可以用滚动数组来实现。
f[i][Now] 代替了 f[i][j] , f[i][Now^1] 代替了 f[i][j-1] 。为了方便,我们把 f[][Now^1] 叫做 f[][Last] 。
这样空间复杂度为 O(n) 。满足空间限制。
2) 对于时间的优化。
考虑优化状态转移的过程。
对于 f[i][Now] ,其实是 f[mink][Last]...f[i-1][Last] 这一段 f[k][Last] 的和,mink 是满足 Sum[i] - Sum[k] <= Len 的最小的 k ,那么,对于从 1 到 n 枚举的 i ,相对应的 mink 也一定是非递减的(因为 Sum[i] 是递增的)。我们记录下 f[1][Last]...f[i-1][Last] 的和 Sumf ,mink 初始设为 1,每次对于 i 将 mink 向后推移,推移的同时将被舍弃的 p 对应的 f[p][Last] 从 Sumf 中减去。那么 f[i][Now] 就是 Sumf 的值。
这样时间复杂度为 O(nm) 。满足时间限制。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; const int MaxN = 50000 + 5, Mod = 10007; int n, m, Len, MaxLen, Ans, Sumf;
int A[MaxN], Sum[MaxN], f[MaxN][2]; inline int gmax(int a, int b) {
return a > b ? a : b;
}
inline int gmin(int a, int b) {
return a < b ? a : b;
} bool Check(int x) {
if (x < MaxLen) return false;
int Add = 0, Cut = 0;
for (int i = 1; i <= n; i++) {
if (Add + A[i] > x) {
Cut++;
if (Cut > m) return false;
Add = 0;
}
Add += A[i];
}
return true;
} int main()
{
scanf("%d%d", &n, &m);
MaxLen = 0;
memset(Sum, 0, sizeof(Sum));
for (int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
MaxLen = gmax(MaxLen, A[i]);
Sum[i] = Sum[i - 1] + A[i];
}
int l = 0, r = 50000000, mid;
while (l <= r) {
mid = (l + r) >> 1;
if (Check(mid)) r = mid - 1;
else l = mid + 1;
}
Len = r + 1;
memset(f, 0, sizeof(f));
Ans = 0;
int Now = 0, Last = 1, Mink;
for (int i = 0; i <= m; i++) {
Sumf = 0;
Mink = 1;
for (int j = 1; j <= n; j++) {
if (i == 0) {
if (Sum[j] <= Len) f[j][Now] = 1;
else f[j][Now] = 0;
}
else {
while (Mink < j && Sum[j] - Sum[Mink] > Len) {
Sumf -= f[Mink][Last];
Sumf = (Sumf + Mod) % Mod;
++Mink;
}
f[j][Now] = Sumf;
}
Sumf += f[j][Last];
Sumf %= Mod;
}
Ans += f[n][Now];
Ans %= Mod;
Now ^= 1;
Last = Now ^ 1;
}
printf("%d %d\n", Len, Ans);
return 0;
}
[BZOJ 1044] [HAOI2008] 木棍分割 【二分 + DP】的更多相关文章
- BZOJ 1044: [HAOI2008]木棍分割(二分答案 + dp)
第一问可以二分答案,然后贪心来判断. 第二问dp, dp[i][j] = sigma(dp[k][j - 1]) (1 <= k <i, sum[i] - sum[k] <= ans ...
- BZOJ 1044: [HAOI2008]木棍分割
Description 求 \(n\) 根木棍长度为 \(L\) ,分成 \(m\) 份,使最长长度最短,并求出方案数. Sol 二分+DP. 二分很简单啊,然后就是方案数的求法. 状态就是 \(f[ ...
- 【bzoj1044】[HAOI2008]木棍分割 二分+dp
题目描述 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且 ...
- Luogu P2511 [HAOI2008]木棍分割 二分+DP
思路:二分+DP 提交:3次 错因:二分写萎了,$cnt$记录段数但没有初始化成$1$,$m$切的次数没有$+1$ 思路: 先二分答案,不提: 然后有个很$naive$的$DP$: 设$f[i][j] ...
- 【BZOJ】1044: [HAOI2008]木棍分割 二分+区间DP
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1044 Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, ...
- bzoj 1044 [HAOI2008]木棍分割(二分+贪心,DP+优化)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1044 [题意] n根木棍拼到一起,最多可以切m刀,问切成后最大段的最小值及其方案数. ...
- bzoj 1044: [HAOI2008]木棍分割【二分+dp】
对于第一问二分然后贪心判断即可 对于第二问,设f[i][j]为已经到j为止砍了i段,转移的话从$$ f[i][j]=\sigema f[k][j-1] (s[j]-s[k-1]<=ans) 这里 ...
- BZOJ 1044: [HAOI2008]木棍分割 DP 前缀和优化
题目链接 咳咳咳,第一次没大看题解做DP 以前的我应该是这样的 哇咔咔,这tm咋做,不管了,先看个题解,再写代码 终于看懂了,卧槽咋写啊,算了还是抄吧 第一问类似于noip的那个跳房子,随便做 这里重 ...
- bzoj 1044 [HAOI2008]木棍分割——前缀和优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1044 前缀和优化. 但开成long long会T.(仔细一看不用开long long) #i ...
随机推荐
- 命令行启动tomcat,怎么配置
进和你tomcat的安装目录进入里面bin目录下列可以直接在cmd中运行(要进入tomcat的bin目录),也可直接双击startup.bat 启动tomcatshutdown.bat 关闭tomca ...
- Ubuntu上OpenStack DashBoard主题修改的方案
最近终于把OpenStack的整个初步环境安装部署并配置成功,后续工作就是安装一些可选项了,如Cinder.Swift部件了.我们的整个项目采用的颜色方案主要为清淡色系,蓝色为主,可OpenStack ...
- Js获取标签高度
能力有限:问个问题,标签相对页面高度,是怎么写? 鼠标的横坐标,X轴: event.clientX; 鼠标的竖坐标,Y轴: event.clientY; 网页可见区域宽: document.bo ...
- 嵌入值和序列化LOB
Embedded Value 把一个对象映射成另一个对象表中的若干字段. OO系统中会有很多小对象(DataRange,Money).而作为表在DB中毫无意义. 默认想法是把一个对象保存为一个表. 但 ...
- (转)MongoDB 3.0 WT引擎参考配置文件
mongodb 3.0 改变很多,从2.6版本升级到3.0要关注的细节很多,如权限等等.3.0在数据存储引擎上更换成了wiredTiger,在数据压缩方面很有效,解决大数据量问题的情况下,磁盘不够用的 ...
- 初识sass
大图:http://images2015.cnblogs.com/blog/730765/201605/730765-20160529113743209-72994369.png
- poj 3268 Silver Cow Party
S ...
- 《RPM源码包的制作》RHEL6
一下rpm包的创建不含编译部分: 首先写个脚本,这个脚本是你想干的事..useradd.sh是我写的脚本,批量添加20个用户.我们创建一个目录,将脚本放进去: 将此目录压缩: 我们将校验的key导出: ...
- LINQ to XML(1)
LINQ to XML可以两种方式和XML配合使用.第一种方式是作为简化的XML操作API,第二种方式是使用LINQ查询工具.下面我使用的是第二种方式. 主要内容:用LINQ查询语句对XML文件里的数 ...
- ASP.NET MVC 2 验证
来源:http://www.cnblogs.com/jhxk/articles/2612885.html 只为把自己觉的好的存起来 对用户输入的验证以及强制业务规则/逻辑是大多数web应用的核心需求 ...