Best Cow Fences POJ - 2018 (二分)

Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each field contains a certain number of cows, 1 <= ncows <= 2000.

FJ wants to build a fence around a contiguous group of these fields in order to maximize the average number of cows per field within that block. The block must contain at least F (1 <= F <= N) fields, where F given as input.

Calculate the fence placement that maximizes the average, given the constraint.

Input

* Line 1: Two space-separated integers, N and F.

* Lines 2..N+1: Each line contains a single integer, the number of cows in a field. Line 2 gives the number of cows in field 1,line 3 gives the number in field 2, and so on.

Output

* Line 1: A single integer that is 1000 times the maximal average.Do not perform rounding, just print the integer that is 1000*ncows/nfields.

Sample Input

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

Sample Output

6500


题意:n块田地,每块田地有cows【i】头牛,求出一个长度不小于F的子段,使子段牛的平均数最大。
思路:我们令 avr = sum【i,j】/(i-j+1)
那么这题就是 求是avr的最大值,我们二分枚举ans,判断 avr 是否不小于 ans,即avr >= ans,为了不维护(i-j+1)的值,变形成sum【i,j】 - ans*(i-j+1) >= 0,
我们把原数组cows【i】-ans,那么Sum【i,j】 = sum【i,j】-ans(i-j+1)。
现在关键就是取得一个  max{Sum【i,j】},对于Sum【i,j】,我们可以用前缀和相减的方式求得,sum(i)-min(sum(j)), 0 <= j <= i-F。

坑点:注意最后答应的是二分的R值,我打印L值Wa的怀疑人生.而且题目要求精度是1e-4,当我们枚举的精度不小于题目要求精度的时候L和R值都是OK的
我感觉是如果两个值转换为整数不同的话,R值转换的整数值在L~R区间内的,而l转换的值是小于l的,如果两个值转换的值相同,打印那个都行,且整数肯定小于L。

其实像是最大值最小,最小值最大,都可以用二分解决,答案是单调的,这题还有种用凸包方法写的,以后再填坑吧。

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 
 5 const int maxn = 1e5+5;
 6 int n,f;
 7 int cows[maxn];
 8 const double eps = 1e-8;
 9 
10 bool solve(double x,int f)
11 {
12     double fcows[n+1];
13     double sum[n+1];
14     for(int i=1;i<=n;i++)fcows[i] = cows[i] - x;
15     for(int i=1;i<=n;i++)sum[i] = sum[i-1]+fcows[i];
16     double ans = -1e10,minn = 1e10;
17     for(int i=f;i<=n;i++)
18     {
19         minn = min(minn,sum[i-f]);
20         ans = max(ans,sum[i]-minn);
21     }
22     return ans >= 0;
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&f);
27     double low=0;
28     double high = 0;
29     for(int i=1;i<=n;i++)
30     {
31         scanf("%d",&cows[i]);
32         high += cows[i];
33     }
34     while(low + eps < high)
35     {
36         double mid = (low+high)/2;
37         if(solve(mid,f))low = mid;
38         else high = mid;
39     }
40     printf("%d\n",(int)(1000*high)); 
41 }
View Code

 




转载于:https://www.cnblogs.com/iwannabe/p/10160942.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值