最佳牛围栏(二分)

农夫约翰的农场由 NN 块田地组成,每块地里都有一定数量的牛,其数量不会少于 $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



 
由题意可知, 答案为$MAX(sum(a_i, a_{i+1},a_{i+2},...,a_{j})){j-ige L}$
根据前缀和的性质, 我们可以推导得如下公式:
$MAX(sum_{j}-sum_{i}){0le i le j - L}$
$令ming = MIN(sum_i){0 < i < j - l}$
$则MAX(sum_j - sum_i){0le i le j - L}$
$=MAX(sum_j - ming){j ge L}$
 
 
 1 #include <iostream>
 2 #include <algorithm>
 3 #include <map>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 const int MAXN = 1e5 + 3;
 8 
 9 int cow[MAXN];
10 double sum[MAXN];
11 int n, f;
12 bool check(double avg)
13 {
14     for (int i = 1; i <= n; ++i)
15     {
16         sum[i] = sum[i - 1] + cow[i] - avg;
17     }
18 
19     double ming = 1e10, ans = -1e10;
20     for (int i = f; i <= n; ++i)
21     {
22         ming = min(ming, sum[i - f]);
23         ans = max(ans, sum[i] - ming);
24     }
25 
26     return ans >= 0;
27 }
28 
29 int main()
30 {
31     cin >> n >> f;
32     for (int i = 1; i <= n; ++i)
33     {
34         cin >> cow[i];
35     }
36     double eps = 1e-5, r = 1e6, l = -1e6;
37     while (r - l > eps)
38     {
39         double mid = (l + r) / 2;
40         if (check(mid))
41         {
42             l = mid;
43         }
44         else
45             r = mid;
46     }
47 
48     cout << int(r * 1000) << endl;
49     return 0;
50 }
AC Code
 
原文地址:https://www.cnblogs.com/daremo/p/15057993.html