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

打滚动数组

#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就完了

代码

#include<bits/stdc++.h>
#define re register
#define i_ inline
#define huan cout<<endl
#define ll int
#define A 50010
ll n,m,before[A],a[A],maxx=-1,last[A],sum[A],su[A],jilu;short f[50101][2];
using namespace std;
#define mod 10007
inline ll read()
{
ll f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f*x;
}
i_ bool find(ll x)
{
ll zhizhen=0,zan=0,add=0,dangqian;
if(x<maxx)
return false;
while(zhizhen<=n)
{
zhizhen++;
if(add+a[zhizhen]<=x)
{
add+=a[zhizhen];
}
else
{
zan++;
add=a[zhizhen];
dangqian=zhizhen;
}
}
if(add!=0)
zan++;
return (zan<=m?1:0);
}
i_ ll er()
{
ll l=0,r=sum[n],mid,ans;
while(l<=r)
{
mid=(l+r)>>1;
if(find(mid)==1)
ans=mid,r=mid-1;
else
l=mid+1;
}
// printf("m=%lld\n",jilu);
return ans;
}
void tiaos(bool x)
{
printf("记录=%lld\n",jilu);
if(x)
{
for(ll i=1;i<=n;i++)
printf("last[%lld]=%lld ",i,last[i]);
cout<<endl;
for(ll i=1;i<=n;i++,puts(""))
for(ll j=0;j<=m;j++)
printf("f[%lld][%lld]=%lld ",i,j,f[i][j]);
return ;
}
else
{
for(ll i=1;i<=n;i++,puts(""))
for(ll j=0;j<=m;j++)
printf("f[%lld][%lld]=%lld ",i,j,f[i][j]);
}
}
int main()
{
// freopen("out.in","r",stdin);
// freopen("wrong.out","w",stdout);
n=read(),m=read();
m+=1;
for(ll i=1;i<=n;i++)
{
a[i]=read();
sum[i]=sum[i-1]+a[i];
maxx=max(a[i],maxx);
} ll cun=er(),zhe=1; m=m-1; ll uscao=0;
for(ll i=1;i<=n;i++)
{
if(sum[i]>cun) break;
else f[i][0]=1;
}
for(ll i=1;i<=n;i++)
last[i]=lower_bound(sum+1,sum+i+1,sum[i]-cun)-sum;
for(ll j=1;j<=m;j++)
{
for(ll i=1;i<=n;i++)
su[i]=su[i-1]+f[i][j&1^1],f[i][j&1]=0;
for(ll i=j+1;i<=n;i++)
f[i][j&1]=(f[i][j&1]+su[i-1]-su[last[i]-1])%mod;
uscao=(uscao+f[n][j&1])%mod;
} // tiaos(1);
cout<<cun<<" "<<uscao;
}

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. 用 shell 脚本制造连接频繁中断的场景

    问题的提出 最近在准备客户端的新版本,在内部灰度过程中,发现一类奇怪的 dump,通过查看日志和堆栈,可以确定是因为每次连上后台就被后台断开了.导致多次重连后随机发生的崩溃.dump 和日志都无法提供 ...

  2. c++如何理解map对象的value_type是pair类型

    map 是以 pair形式插入的.map中的元素的类型value_typetypedef pair<const Key, Type> value_type;value_type 被声明为 ...

  3. UVA OJ 623 500!

    500!  In these days you can more and more often happen to see programs which perform some useful cal ...

  4. .Net Core with 微服务 - 架构图

    上一次我们简单介绍了什么是微服务(.NET Core with 微服务 - 什么是微服务 ).介绍了微服务的来龙去脉,一些基础性的概念.有大佬在评论区指出说这根本不是微服务.由于本人的能力有限,大概也 ...

  5. 客户端保存token到sessionStorage

    将token保存到客户端的sessionStorage 一.区分localStorage和sessionStorage localStorage是本地持久化存储 sessionStorage是浏览器会 ...

  6. [Windows] 屏幕截图 - FastStone Capture(FSCapture) v9.4 飞扬时空汉化绿色版(官方地址) 【清晰好用 已验证】

    [Windows] 屏幕截图 - FastStone Capture(FSCapture) v9.4 飞扬时空汉化绿色版(官方地址) [复制链接]     愤怒の葡萄 电梯直达 楼主    发表于 2 ...

  7. docker 日志位置

    日志分两类,一类是 Docker 引擎日志:另一类是 容器日志. Docker 引擎日志 Docker 引擎日志 一般是交给了 Upstart(Ubuntu 14.04) 或者 systemd (Ce ...

  8. centos 6 x64 yum(sohu)

    centos 6 x64 yum(sohu) weixin_34405354 2012-08-23 10:07:35 24 收藏 文章标签: 运维 版权 [base] name=Base baseur ...

  9. Ubuntu20 修改网卡名称

    Ubuntu 修改网卡名称 Ubuntu修改网卡名称 Ubuntu 版本: Ubuntu 20.04 查看当前网卡名称 root@it:~# ip add 1: lo: <LOOPBACK,UP ...

  10. Git工作中的使用

    Git工作中的使用 2019-01-16 14:29:31 雯雯木 阅读数 207更多 分类专栏: 自动化测试   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...