很久之前打的题,现在补篇博客

打滚动数组

#E. 木棍分割

Accepted

100

1712 ms

1512 KiB

 

2019-05-07 17:01:23

Short 不打滚动数组

#419. [HAOI2008]木棍分割

Accepted

100

5219 ms

100960 KiB

2019-05-07 15:12:41

木棍分割 题解

木棍分割

内存限制:128 MiB时间限制:3000 ms标准输入输出

题目类型:传统评测方式:文本比较

提交提交记录返回比赛

题目描述

有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

数据范围与提示

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

二分答案+dp滚动数组

第一步 二分答案求长度

每次枚举木棍可以分成的值下界为所有木棍最小值上界为所有木棍最大值

当 当前值可以分成的时候,比它小的值可能可以分成故让当前r=mid-1

当 当前值不可以分成的时候比它大的值可能分成故让l=mid+1

当r>mid时得到最终答案

然后find函数检验当前值是否可以分成

具体操作:枚举!

初始化add=0,指针=0,块数=0;

只需要扫一遍当add<=x的时候直接在add加上当前这个值;否则令分成的块数++ 并且令add值重新附成当前指针指向的木棍长度

值得注意的一点是 当指针已经指向最后一个数的时候 若add不为0 块数需要+1

最后比较块数与m即可

第二步 dp求方案数

首先暴力枚举求方案数肯定会超时,很自然的想到统计方案需要用dp

首先想要至少开二维 当前切割位置可能由任何满足之间木棍长度之和<=第一步求得的答案   的切割位置转移过来

需要枚举每一根木棍(枚举当前切割的位置) ,每一个前一个切割的位置,和切割的次数

可以看到是n2*m复杂度 还不如打一个暴力 同样是t掉

dp暴力转移式$f[i][j]+=f[k][j-1](if(sum[i]-sum[k-1]<=maxn)$

善良的出题人肯定不会让你AC的

你会得到0分的好成绩

Time Limit Exceeded

0

30150 ms

然后我们要考虑一些优化

我们可以看到事实上一些位置是加重了的

在每一个切割次数下要枚举一遍k 每次都枚举了k 但事实上每个木棍长是始终不变的

每次枚举一遍就太区区了

我们需要一个数据结构来快速查询每一段所代表的值并且维护一个before数组代表在其之前最长的一段<=第一步求的答案

before可以暴力去求也可以用 lower_bound

for(ll i=1;i<=n;i++)

last[i]=lower_bound(sum+1,sum+i+1,sum[i]-cun)-sum;

理解一下

例如 9 3

5 4 3 2 1 2 3 4 5

这一组数据对应 before为

1 1 1 1 2 2 3 5 7

cun=7;

sum 值 5 9 12 14 15 17 20 24 29

对应下标 1 2  3  4  5   6   7  8  9

last[1]=1 sum[1]-cun=-4

last[2]=1 sum[2]-cun=0

last[3]=1 sum[3]-cun=3

last[4]=1 sum[4]-cun=5

last[5]=2 sum[5]-cun=6

last[6]=2 sum[6]-cun=8

last[7]=3 sum[7]-cun=11

last[8]=5 sum[8]-cun=15

last[9]=7 sum[9]-cun=20

lower_查到的下标 事实就是sum[i]-sum[now]<=cun 其实还是挺好理解的

然后就是数据结构

事实上 考虑到区间查值 我们可以用前缀和(当然树状数组不行 并没有单点修改仅仅是每次要查值而已 前缀和维护是o(1)  树状数组o(logn))

然后dp就完了

代码

  1. #include<bits/stdc++.h>
  2. #define re register
  3. #define i_ inline
  4. #define huan cout<<endl
  5. #define ll int
  6. #define A 50010
  7. ll n,m,before[A],a[A],maxx=-1,last[A],sum[A],su[A],jilu;short f[50101][2];
  8. using namespace std;
  9. #define mod 10007
  10. inline ll read()
  11. {
  12. ll f=1,x=0;char ch=getchar();
  13. while(ch<'0'||ch>'9')
  14. {
  15. if(ch=='-') f=-1;
  16. ch=getchar();
  17. }
  18. while(ch>='0'&&ch<='9')
  19. {
  20. x=(x<<1)+(x<<3)+(ch^48);
  21. ch=getchar();
  22. }
  23. return f*x;
  24. }
  25. i_ bool find(ll x)
  26. {
  27. ll zhizhen=0,zan=0,add=0,dangqian;
  28. if(x<maxx)
  29. return false;
  30. while(zhizhen<=n)
  31. {
  32. zhizhen++;
  33. if(add+a[zhizhen]<=x)
  34. {
  35. add+=a[zhizhen];
  36. }
  37. else
  38. {
  39. zan++;
  40. add=a[zhizhen];
  41. dangqian=zhizhen;
  42. }
  43. }
  44. if(add!=0)
  45. zan++;
  46. return (zan<=m?1:0);
  47. }
  48. i_ ll er()
  49. {
  50. ll l=0,r=sum[n],mid,ans;
  51. while(l<=r)
  52. {
  53. mid=(l+r)>>1;
  54. if(find(mid)==1)
  55. ans=mid,r=mid-1;
  56. else
  57. l=mid+1;
  58. }
  59. // printf("m=%lld\n",jilu);
  60. return ans;
  61. }
  62. void tiaos(bool x)
  63. {
  64. printf("记录=%lld\n",jilu);
  65. if(x)
  66. {
  67. for(ll i=1;i<=n;i++)
  68. printf("last[%lld]=%lld ",i,last[i]);
  69. cout<<endl;
  70. for(ll i=1;i<=n;i++,puts(""))
  71. for(ll j=0;j<=m;j++)
  72. printf("f[%lld][%lld]=%lld ",i,j,f[i][j]);
  73. return ;
  74. }
  75. else
  76. {
  77. for(ll i=1;i<=n;i++,puts(""))
  78. for(ll j=0;j<=m;j++)
  79. printf("f[%lld][%lld]=%lld ",i,j,f[i][j]);
  80. }
  81. }
  82. int main()
  83. {
  84. // freopen("out.in","r",stdin);
  85. // freopen("wrong.out","w",stdout);
  86. n=read(),m=read();
  87. m+=1;
  88. for(ll i=1;i<=n;i++)
  89. {
  90. a[i]=read();
  91. sum[i]=sum[i-1]+a[i];
  92. maxx=max(a[i],maxx);
  93. }
  94.  
  95. ll cun=er(),zhe=1; m=m-1; ll uscao=0;
  96. for(ll i=1;i<=n;i++)
  97. {
  98. if(sum[i]>cun) break;
  99. else f[i][0]=1;
  100. }
  101. for(ll i=1;i<=n;i++)
  102. last[i]=lower_bound(sum+1,sum+i+1,sum[i]-cun)-sum;
  103. for(ll j=1;j<=m;j++)
  104. {
  105. for(ll i=1;i<=n;i++)
  106. su[i]=su[i-1]+f[i][j&1^1],f[i][j&1]=0;
  107. for(ll i=j+1;i<=n;i++)
  108. f[i][j&1]=(f[i][j&1]+su[i-1]-su[last[i]-1])%mod;
  109. uscao=(uscao+f[n][j&1])%mod;
  110. }
  111.  
  112. // tiaos(1);
  113. cout<<cun<<" "<<uscao;
  114. }

HAOI2008 木棍分割 数据结构优化dp+二分答案的更多相关文章

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

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

  2. BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP+单调队列

    BZOJ_1044_[HAOI2008]木棍分割_二分答案+DP Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个 ...

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

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

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

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

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

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

  6. BZOJ 1044 木棍分割 解题报告(二分+DP)

    来到机房刷了一道水(bian’tai)题.题目思想非常简单易懂(我的做法实际上参考了Evensgn 范学长,在此多谢范学长了) 题目摆上: 1044: [HAOI2008]木棍分割 Time Limi ...

  7. 1044: [HAOI2008]木棍分割

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

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

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

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

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

随机推荐

  1. 一句 Task.Result 就死锁, 这代码还怎么写?

    一:背景 1. 讲故事 前些天把 .NET 高级调试 方面的文章索引到 github 的过程中,发现了一个有意思的评论,详见 文章,截图如下: 大概就是说在 Winform 的主线程下执行 Task. ...

  2. 简单介绍下自动化框架:Robot Framework

    一.简介: Robot Framework:Robot Framework是由Python编写的一款功能丰富并且扩展性强的自动化测试框架,也可以在Java和 .NET 上运行. HttpRunner: ...

  3. ZOHO荣登“2020中国ToB行业年度企业影响力”榜单

    近日,3WToB行业头条正式揭晓<2020中国ToB行业年度榜单 · 企业影响力榜>. 此次评选,ToB行业头条联合3W集团.50+知名投资机构.60+权威媒体及资深行业人士,进行深度调研 ...

  4. 克鲁斯卡尔(Kruskal)算法

    概览 相比于普里姆算法(Prim算法),克鲁斯卡尔算法直接以边为目标去构建最小生成树.从按权值由小到大排好序的边集合{E}中逐个寻找权值最小的边来构建最小生成树,只要构建时,不会形成环路即可保证当边集 ...

  5. centos7安装powershell和powercli

    poershell github https://github.com/PowerShell/PowerShell/releases 本次采用github下载对应的rpm进行安装 windows下安装 ...

  6. CentOS 7 调整home大小

    把/home内容备份,然后将/home文件系统所在的逻辑卷删除,扩大/root文件系统,新建/home: tar cvf /tmp/home.tar /home #备份/home umount /ho ...

  7. Mysql体系结构管理

    1.客户端与服务端模型 1)数据是一个典型的C/S结构的服务 1.mysql自带的客户端工具 mysql mysqladmin mysqldump 3.mysql是一个二进制程序,后台守护进程 单进程 ...

  8. OpenStack平台功能性测试工具Tempest安装

    社区对OpenStack平台功能性的测试工具采用Tempest,性能测试采用Rally. 1.什么是Tempest tempest├── api # API的测试集├── cli # OpenStac ...

  9. 014.Python函数

    一 函数的概念 1.1 函数的含义 功能 (包裹一部分代码 实现某一个功能 达成某一个目的) 1.2 函数特点 可以反复调用,提高代码的复用性,提高开发效率,便于维护管理 1.3 函数的基本格式 # ...

  10. 网上的说TB6560存在的问题

    https://www.amobbs.com/thread-5506456-2-1.html