【算法刷题】AcWing 102. 最佳牛围栏——二分

该博客介绍了如何运用二分查找算法解决寻找一段连续田地中牛的最大平均值问题。通过建立一个判定条件,计算是否存在一段长度至少为F的连续区域,使得平均牛数达到或超过给定值avg。博主详细阐述了如何使用动态规划和前缀和技巧优化计算过程,并给出了完整的C++代码实现。最终,通过浮点数二分查找确定最大平均值并输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

农夫约翰的农场由 NNN 块田地组成,每块地里都有一定数量的牛,其数量不会少于 111 头,也不会超过 200020002000 头。

约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。

围起区域内至少需要包含 FFF 块地,其中 FFF 会在输入中给出。

在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。

输入格式
第一行输入整数 NNNFFF,数据间用空格隔开。

接下来 NNN 行,每行输入一个整数,第 i+1i+1i+1 行输入的整数代表第 iii 片区域内包含的牛的数目。

输出格式
输出一个整数,表示平均值的最大值乘以 100010001000向下取整向下取整向下取整 之后得到的结果。

数据范围
1≤N≤1000001 \leq N \leq 1000001N100000
1≤F≤N1 \leq F \leq N1FN
输入样例

10 6
6 
4
2
10
3
8
5
9
4
1

输出样例

6500
①分析

使用二分可以将问题转化为一个判定问题,相当于给我们多提供了一个条件即给定一个avg,判断是否存在一个方案,使其平均值≥avg让每个ai−=avg,问题就变成了是否存在一段长度≥F并且和是≥0下面可以用DP的思想,将所有的段分成n类,每一类的右端点分别为a1...an假设现在的右端点为ak,那么这一类的左端点为a1∼ak−F+1要快速求得这一段的和可以用前缀和,即在−=avg后将数组处理为前缀和数组S那么每次只需要算得Sk−Si−1(i=1∼k−F+1,i−1=0∼k−F)这样对于每一类就只需要求Sk−S0∼k−F中的最小值因为k是不断在增加的,那么前一段的最小值可以只用一个变量mins来维护最后就只需要用二分来枚举出avg即可如果一个方案求得的max≥0即该方案合理,那么avg就需要放大,如果max<0那么avg就需要缩小放大对应于二分就是l=mid,缩小就是r=mid 使用二分可以将问题转化为一个判定问题,相当于给我们多提供了一个条件\\ 即给定一个avg,判断是否存在一个方案,使其平均值\geq avg\\ 让每个a_i-=avg,问题就变成了是否存在一段长度\geq F并且和是\geq 0\\ 下面可以用DP的思想,将所有的段分成n类,每一类的右端点分别为a_1...a_n\\ 假设现在的右端点为a_k,那么这一类的左端点为a_1 \sim a_{k-F+1}\\ 要快速求得这一段的和可以用前缀和,即在-=avg后将数组处理为前缀和数组S\\ 那么每次只需要算得S_k-S_{i-1}(i=1\sim k-F+1,i-1=0\sim k-F)\\ 这样对于每一类就只需要求S_k-S_{0\sim k-F中的最小值}\\ 因为k是不断在增加的,那么前一段的最小值可以只用一个变量mins来维护\\ 最后就只需要用二分来枚举出avg即可\\ 如果一个方案求得的max \geq 0即该方案合理,那么avg就需要放大,如果max< 0那么avg就需要缩小\\ 放大对应于二分就是l=mid,缩小就是r=mid 使用二分可以将问题转化为一个判定问题,相当于给我们多提供了一个条件即给定一个avg,判断是否存在一个方案,使其平均值avg<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricky_0528

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值