loj10012 Best Cow Fences

题目描述

原题来自:USACO 2003 Mar. Green

给定一个长度为 N 的非负整数序列 A ,求一个平均数最大的,长度不小于 L 的子段。

输入格式

第一行用空格分隔的两个整数 N 和 L

第二行为 N 个用空格隔开的非负整数,表示A_i 

输出格式

输出一个整数,表示这个平均数的 1000 倍。不用四舍五入,直接输出。

样例

样例输入

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

样例输出

6500

数据范围与提示

n<=1e5,A_i<=2000。

______________________________________________

USACO的题目,很经典!

求的是长度不小于L,平均值最大的子序列。输出平均值。

二分平均值,然后让序列中的后有的数都减去二分的平均值,这样如果某个子序列的所有数的和大于0,则这个子序列的平均值大于二分的平均值!

题目不算难做,但是最后结果的处理比较麻烦,保留三位小数但不四舍五入!!

处理了好几次 !

______________________________________________ 
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,l;
double sz[maxn],f[maxn];
bool pd(double x)
{
    for(int i=1;i<=n;++i)f[i]=sz[i]-x;
    double mn=0;
    for(int i=1;i<l;++i)f[i]=f[i-1]+f[i];
    for(int i=l;i<=n;++i)
    {
        f[i]=f[i]+f[i-1];
        mn=min(mn,f[i-l]);
        if(f[i]>=mn)return 1;
    }
    return 0;
}

int main()
{
    scanf("%d%d",&n,&l);
    for(int i=1;i<=n;++i)scanf("%lf",sz+i);
    double l=0,r=2000;
    while(l+1e-8<r)
    {
        double mid=(l+r)/2;
        if(pd(mid))l=mid;
        else r=mid;
    }
    cout<<int(r*1000);
    return 0;
}
原文地址:https://www.cnblogs.com/gryzy/p/13985122.html