Best Cow Fences(二分+前綴和)

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個點,要求使得在一段長度不小於L的子區間中每個點得到的平均值最大,並輸出這個最大的平均值。

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include<algorithm>
#include<iomanip>
#define SIS std::ios::sync_with_stdio(false)
#define ll long long
#define INF 0x3f3f3f3f
#define mod 998244353
const int MAXN = 1e9 + 7;
const double PI = 3.14159265358979;
using namespace std;
const int N = 1e5 + 5;
/*int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
ll _power(int a, int b)//計算a^b;
{
	int ans=1, res=a;
	while(b){
		if(b&1) ans=ans*res%mod;
		res=res*res%mod;
		b>>=1;
	}
	return ans%mod;
	*/
double a[N], b[N], s[N];
double l, r,mid;
int n, f;
int main() {
	scanf("%d%d", &n, &f);
	for (int i = 1; i <= n; i++) {
		scanf("%lf", &a[i]);
	}
	l = -1e6; r = 1e6;
	s[0] = 0;
	while (r-l>1e-5) {
		mid = (l + r) / 2;
		for (int i = 1; i <= n; i++) {
			b[i] = a[i] - mid;
		}
		for (int i = 1; i <= n; i++) {//前綴和
			s[i] = s[i - 1] + b[i];
		}
		double maxn, minn;
		maxn = -1e10; minn = 1e10;
		for (int i = f; i <= n; i++) {
			minn = min(minn, s[i - f]);
			maxn = max(maxn, s[i] - minn);
		}
		if (maxn >= 0)  l = mid;
		else r = mid;
	}
	printf("%d\n", (int)(r * 1000));
	return 0;
}

思路:

二分答案+判定: 
1、二分平均值 average 
2、將所有的點減去 average 
3、對區間求前綴和。 
4、枚舉每個長度爲 L 的子區間,減去當前最小值,這時長度至少爲 L(並且可能大於,這是滿足要求的)。設:這次掃描得到的最大的 和 爲 ans 
5、 
(1)、如果 這次找到的 ans 是小於0的,那麼意味着,當前的 average 太大了,以至於沒有任何一個子區間的平均值是能夠達到當前的 average ,即:不存在滿足當前 average 的情況。 
(2)、否則 ans 大於等於0,就說明:有能夠達到當前 average 的子區間方案,average 是可能是答案的。 
6、對於 ans<0,則要變小 average,那麼二分的區間就應往小的方向取;對於 ans>=0,則還可以變大 average 去嘗試,區間往大的方向取。 
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章