• POJ 2018 Best Cow Fences(二分+最大连续子段和)


    Best Cow Fences
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 14601   Accepted: 4720

    Description

    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
    

    Source

     

    【题意】

     

    给定一个正整数数列A,求一个平均数最大的、长度不小于L的子段。

     

     

    【分析】

     

    二分答案,判定是否存在一个长度不小于L的子段,平均数不小于二分的值。如果把数列中的每个数都减去二分的值,就转换为判定“是否存在一个长度不小于L的子段,子段和非负”。

     

    <==>求一个子段,使得它的和最大,且子段的长度不小于L

     

    子段和可以转换为前缀和相减的形式,即设sumj表示Ai~Aj的和,

     

    则有:max{A[j+1]+A[j+2].......A[i] } ( i-j>=L ) = max{ sum[i] - min{ sum[j] }(0<=j<=i-L) }L<=i<=n

     

    仔细观察上面的式子可以发现,随着i的增长,j的取值范围 0~i-L 每次只会增大1。换言之,每次只会有一个新的取值进入 min{sumj} 的候选集合,所以我们没必要每次循环枚举j,只需要用一个变量记录当前的最小值,每次与新的取值 sum[i-L] min 就可以了。

     

    【代码】

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int n,m;double a[N],b[N],sum[N];
    double l,r,mid,eps=1e-6;
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%lf",a+i),l=min(l,a[i]),r=max(r,a[i]);
    	while(r-l>eps){
    		mid=(l+r)/2;
    		for(int i=1;i<=n;i++) b[i]=a[i]-mid;
    		for(int i=1;i<=n;i++) sum[i]=sum[i-1]+b[i];
    		double res=-1e10,mn=1e10;
    		for(int i=m;i<=n;i++){
    			mn=min(mn,sum[i-m]);
    			res=max(res,sum[i]-mn);
    		}
    		if(res>=0) l=mid;
    		else r=mid;
    	}
    	printf("%d
    ",int(r*1000));
    	return 0;
    }

     

     

  • 相关阅读:
    在线用户数与并发用户数的区别和比例关系
    MYSQL中数据类型介绍
    5分钟教你搞定RAID模式
    nginx与fastdfs配置详解与坑
    Fastdfs group通过添加硬盘扩容
    fastDfs配置文件tracker.conf配置详解
    FastDFS配置详解之Storage配置
    mysql修改库名
    vCenter Server Appliance(VCSA )6.7部署指南
    如何知道一个函数的执行时间简单案例
  • 原文地址:https://www.cnblogs.com/shenben/p/10415470.html
Copyright © 2020-2023  润新知