最佳牛围栏
Posted maktub-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最佳牛围栏相关的知识,希望对你有一定的参考价值。
题目链接
题意
把一个长度为N的序列取出一段长度不小于F的子段,求平均值最大的子段的平均值。
思路
答案似乎不容易看出单调性。。。
换个思路, 一段序列减去平均值后得到的序列, 序列和一定为0.
如果减去的值小于平均值, 则序列和为正, 反之为负。
可以二分一个值, 然后减去这个值, 如果序列中长度不小于F的最大子段和为正, 说明平均值可以再大一些。。
单调性就可以看出来了: 二分值越大, 序列所有数减去二分值后得到的最大子段段和就越小。
关键便是快速判断最大子段和。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<vector> #include<set> #include<cmath> using namespace std; const int mx = 1e5 + 5; const int inf = 1e9; inline void fre() freopen("1.txt", "w", stdout); int n, L; double a[mx], sum[mx]; inline bool check(double mid) sum[0] = 0; double x; for(int i = 1; i <= n; i++) x = a[i] - mid, sum[i] = sum[i-1] + x; double minn = inf, res = -inf; for(int i = L; i <= n; i++) minn = min(minn, sum[i-L]); res = max(res, sum[i] - minn); if(res >= 0) return 1; return 0; int main() //fre(); cin >> n >> L; double l = inf, r = 0; for(int i = 1; i <= n; i++) scanf("%lf", &a[i]), l = min(l, a[i]), r = max(r, a[i]); while(r - l > 0.000001) double mid = (l+r)/2; if(check(mid)) l = mid; else r = mid; printf("%d\n", (int)(r*1000)); return 0;
以上是关于最佳牛围栏的主要内容,如果未能解决你的问题,请参考以下文章