USACO 最佳牛围栏 (二分答案+前缀和+双指针)

题面

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

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

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

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

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

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

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

数据范围
1≤N≤100000
1≤F≤N
输入样例:
10 6
6
4
2
10
3
8
5
9
4
1
输出样例:
6500

思路

暴力枚举n方,本题数据量十万,直接炸裂。果断二分答案,二分了答案之后我们考虑如何写判定函数。因为我们二分的是平均值,那么这里有一个小技巧,就是拿所有元素的值减去平均值。然后我们要求的是某段长度大于m区间,那么我们对这个数组施加前缀和操作,最后双指针扫描一遍数组,取出最长的那段判断。

代码实现

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=100010;
int n,m;
double sum[maxn];
int a[maxn];
bool check (double mid) {
    for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-mid;
    double minv=0;
    for (int i=0,j=m;j<=n;i++,i++) {
        minv=min (minv,sum[i]);
        if (sum[j]>=minv) return true;
    }
    return false;
}
int main () {
    cin>>n>>m;
    for (int i=1;i<=n;i++) {
        cin>>a[i];
    }
    double l=0,r=2000;
    while (r-l>1e-5) {
        double mid=(l+r)/2;
        if (check (mid)) l=mid;
        else r=mid;
    }
    printf ("%d\n",(int ) (r*1000));
    return 0;
}

原文链接: https://www.cnblogs.com/hhlya/p/13311266.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    USACO 最佳牛围栏 (二分答案+前缀和+双指针)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/367132

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 下午5:29
下一篇 2023年3月2日 下午5:29

相关推荐