BZOJ 1044 HAOI 2008 木棍分割 二分 贪心 动态规划
2016-03-12 20:36
573 查看
真是心烦。。似乎一个sb用脚本拼命交30s的while(1)程序卡评测。。这种缺智商的大抵也就会卡oj了。明明有80s的250s的去卡30s的
第一问 二分贪心即可得到答案max_cut。
第二问 令f[i][j]表示前i根切j次的方案数。那么显然有
f[i][j]=∑f[k][j−1](a[k+1]+⋯+a[i]≤max_cut)
首先可以滚动数组。
然后发现合法区间的两端点始终向右移动,预处理每层dp的前缀和可以将复杂度优化到O(nm)。
如何维护?双端队列。
不过考察代码能力的时候到了。
一些速度不忍直视(7s)。。
一些速度还好(2s)。。
还有因为取模太慢了。。
Submit: 2611 Solved: 967
[Submit][Status][Discuss]
1
1
10
1<=Li<=1000.
第一问 二分贪心即可得到答案max_cut。
第二问 令f[i][j]表示前i根切j次的方案数。那么显然有
f[i][j]=∑f[k][j−1](a[k+1]+⋯+a[i]≤max_cut)
首先可以滚动数组。
然后发现合法区间的两端点始终向右移动,预处理每层dp的前缀和可以将复杂度优化到O(nm)。
如何维护?双端队列。
不过考察代码能力的时候到了。
一些速度不忍直视(7s)。。
一些速度还好(2s)。。
还有因为取模太慢了。。
#include <cstdio> #include <cstring> #define FOR(i,j,k) for(i=j;i<=k;++i) int read() { int s = 0, f = 1; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1; for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0'; return s * f; } int main() { const int N = 50001, mod = 10007; static int sum , a , f , sf , pre , q ; int i, j, l = 2, r, t, s, mid, ans = 0, last = 1, max_cut, n = read(), m = read(); FOR(i,1,n) { sum[i] = sum[i - 1] + (a[i] = read()); if (a[i] > l) l = a[i]; } l -= 1, r = sum ; while (l <= r) { mid = l + r >> 1; t = s = 0; FOR(i,1,n) { s += a[i]; if (s > mid) ++t, s = a[i]; if (t > m) i = 79999; else if (a[i] > mid) i = 79999; } if (i != 80000) max_cut = mid, r = mid - 1; else l = mid + 1; } FOR(i,1,n) { while (sum[i] - sum[last] > max_cut) ++last; pre[i] = last - 1; } for(i = 1; i <= n && sum[i] <= max_cut; ++i) f[i] = 1; FOR(i,1,n) sf[i] = (sf[i - 1] + f[i]) % mod; FOR(i,1,m) { FOR(j,1,n) f[j] = (sf[j - 1] - sf[pre[j]]) % mod; FOR(j,1,n) sf[j] = sf[j - 1] + f[j]; ans += f ; if (ans > mod) ans -= mod; } printf("%d %d", max_cut, ans); return 0; }
1044: [HAOI2008]木棍分割
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2611 Solved: 967
[Submit][Status][Discuss]
Description
有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长度最大的一段长度最小. 并将结果mod 10007。。。Input
输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍的长度.Output
输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.Sample Input
3 21
1
10
Sample Output
10 2HINT
两种砍的方法: (1)(1)(10)和(1 1)(10)数据范围
n<=50000, 0<=m<=min(n-1,1000).1<=Li<=1000.
相关文章推荐
- POJ 1088 记忆化搜索
- 周易六十四卦——山风蛊卦
- python爬虫之lxml
- 现代软件工程第三次作业
- 在GitHub注册账户的过程
- 九度题目1074对称平方数
- VirtualBox Extension Pack 扩展包安装 解决虚拟机usb 摄像头不能识别
- 百度2015春季实习生招聘附加题_今天要吃点好的!
- 系统设计
- Java敏捷开发
- 蓝桥杯 历届试题 包含单词数
- 关于“1010小游戏”的调查报告心得体会
- Jasperreport+ireport 实践操作及web应用
- 个人所得税计算器
- 626A.Robot Sequence
- 第2周作业 2013551623 聂滔
- Linux文本处理工具三剑客之grep
- 新安装的ubuntu,vi输入出问题
- String 比较
- Java内存管理:深入Java内存区域