YbtOJ 二分算法课堂过关 例3 最大均值【二分】【前缀和】
发布日期:2021-05-07 13:09:45 浏览次数:20 分类:精选文章

本文共 1089 字,大约阅读时间需要 3 分钟。

在这里插入图片描述


思路

这道题显然需要二分一个平均值,

问题是小数怎么二分呢?
我们可以定义 l , r , m i d l,r,mid l,r,mid 为double类型,
并在判断时加上一个eps即可。(eps是在函数程序中事先声明的常量,是控制迭代精度的,相当于微积分里面的无限小值)

这个问题解决了,我们发现还有一个问题:

判断当前二分到的平均值是否满足条件是 O ( n 2 ) O(n^2) O(n2),会超时。
首先想到前缀和优化。
此时判断区间为 max ⁡ s u m i − s u m i − j + 1 ( l < i ≤ n , j ≤ i − l ) \max{sum_i-sum_{i-j+1}} (l<i≤n,j≤i-l) maxsumisumij+1(l<in,jil)
不难发现 j j j 只会在 1 1 1~ i − l i-l il 中循环比较,直接 max ⁡ \max max 即可,可以省掉一个for循环。
然后注意让当前区间的 s u m i − j + 1 sum_{i-j+1} sumij+1 最小即可得到较优答案。

C o d e Code Code

#include
#include
#include
using namespace std;const double eps=1e-6;double ans=0,a[100010];int n,k;bool check(double x){ double b[100010]; for(int i=1; i<=n; i++) b[i]=b[i-1]+(a[i]-x); double minn=0,boss=-2147483647; for(int i=k; i<=n; i++) { boss=max(boss,b[i]-minn); minn=min(minn,b[i-k+1]); } if(boss>=0) return 1; else return 0;}int main(){ cin>>n>>k; for(int i=1; i<=n; i++) scanf("%lf",&a[i]); double l=0,r=2000,mid=0; while(l+eps<=r) { mid=(l+r)/2; if(check(mid)) l=mid,ans=max(ans,mid); else r=mid; } cout<
上一篇:YbtOJ 深度搜索课堂过关 例1 拔河比赛【深度优先搜索】
下一篇:YbtOJ 二分算法课堂过关 例1 数列分段【二分】

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2025年03月27日 14时34分44秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章