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; }