最佳牛围栏(前缀和+二分)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最佳牛围栏(前缀和+二分)相关的知识,希望对你有一定的参考价值。
题目描述:
农夫约翰的农场由 NN 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 FF 块地,其中 FF 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数 NN 和 FF ,数据间用空格隔开。
接下来 NN 行,每行输出一个整数,第i+1i+1行输出的整数代表,第ii片区域内包含的牛的数目。
输出格式
输出一个整数,表示围起区域内每块地包含的牛的数量的平均值可能的最大值乘以1000得到的数值。
数据范围
1≤N≤100000
1≤F≤N
输入样例:
10 6
6
4
2
10
3
8
5
9
4
1
输出样例:
6500
首先本题没有出现二分的特征词:“最大值最小” or “最小值最大” 并且给的数列不具备单调性,并且不适于排序,我们看到这种题可以先提出假设 比如,假设这道题用二分能解出
那么我们判断是否存在一个平均值大于等于mid,如果最优解是x,那么mid <= x的时候,必然可以找到一段,其平均值≥mid, 否则 一定找不到
对于二分,二分是二分性而不是单调性 只要满足可以找到一个值一半满足一半不满足即可 而不用满足单调性
那么这个题我们就可以使用二分来解决。
这道题和以前的二分位置,二分精度都不一样,是用到了,二分平均值,然后还有前缀和的一些技巧,求出平均数,每个数减去平均数,然后求前缀和。
AC代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<ctime>
#include<map>
const int INF = 0x3f3f3f3f;
using namespace std;
typedef long long ll;
int i,j,k;
const int N=100005;
int cows[N];
double sum[N];
int n, m;
bool check(double avg)
for(i = 1; i <= n; i++)
sum[i]=sum[i-1]+cows[i]-avg;//求每个数减去二分平均数的前缀和
double minv = 0;
for(i = 0, j = m; j <= n; j++, i++)
minv=min(minv,sum[i]);
if(sum[j]-minv>=0) //这一步保证了区间大小大于等于m
return true;
return false;
int main()
scanf("%d %d", &n, &m);
double l=0, r=0;
for (i = 1; i <= n; i++)
scanf("%d", &cows[i]);
r=max(r,(double)cows[i]);
while(r - l > 1e-5)
double mid = (l + r) / 2;
if(check(mid))
l=mid;
else
r = mid;
printf("%d\\n",(int)(r*1000));
return 0;
以上是关于最佳牛围栏(前缀和+二分)的主要内容,如果未能解决你的问题,请参考以下文章