1 条题解

  • 0
    @ 2025-5-12 16:43:37

    问题描述

    Farmer John的农场由一排NN1N100,0001 \leq N \leq 100,000)块田地组成。每块田地里有一定数量的奶牛,1奶牛数量20001 \leq \text{奶牛数量} \leq 2000

    FJ想要在一块连续的田地周围建一个围栏,以使得该区域内每块田地的平均奶牛数量最大化。这个区域必须包含至少FF1FN1 \leq F \leq N)块田地,其中FF是给定的输入。

    在给定的约束条件下,计算围栏的放置位置,使得平均奶牛数量最大化。

    输入

    • 11行:两个用空格分隔的整数,NNFF
    • 2..N+12..N+1行:每行包含一个整数,表示一块田地里的奶牛数量。第22行给出第11块田地的奶牛数量,第33行给出第22块田地的奶牛数量,以此类推。

    输出

    • 11行:一个整数,表示最大平均值的10001000倍。不要进行四舍五入,只需打印出1000×奶牛数量田地数量1000 \times \frac{\text{奶牛数量}}{\text{田地数量}}的整数部分。

    示例

    输入:

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

    输出:

    6500
    

    解题思路

    为了高效地解决这个问题,我们可以采用二分搜索结合前缀和的方法。具体步骤如下:

    1. 确定平均值的范围:由于每块田地的奶牛数量在1120002000之间,平均值的可能范围也是1120002000
    2. 二分搜索:在1120002000之间进行二分搜索,寻找最大的平均值midmid,使得存在一个长度至少为FF的连续子数组,其平均值至少为midmid
    3. 检查可行性:对于每个midmid,计算前缀和数组prefixprefix,其中prefix[i]=prefix[i1]+(cows[i]mid)prefix[i] = prefix[i-1] + (\text{cows}[i] - mid)。然后检查是否存在一个长度至少为FF的子数组,其和0\geq 0
    4. 维护最小前缀和:为了高效检查,维护一个min_prefixmin\_prefix,表示前iFi-Fprefixprefix的最小值。如果prefix[i]min_prefix0prefix[i] - min\_prefix \geq 0,则存在满足条件的子数组。
    5. 输出结果:最终的最大平均值乘以10001000并取整,即为所求。

    解决代码

    #include <stdio.h>
    #include <math.h>
    #include <algorithm>
    #include <iostream>
    #include <string.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    using namespace std;
    const double dlt=1e-5;
    int n,L;
    double a[100007],b[100007],pre[100007];
    int main() {
    	scanf("%d%d",&n,&L);
    	for(int i=1; i<=n; i++) {
    		scanf("%lf",&a[i]);
    	}
    	double l=-1e6,r=1e6;
    	while(r-l>dlt) {
    		int k=0;
    		double mi=(l+r)/2;
    		double mins=1e10;
    		for(int i=1; i<=n; i++) {
    			b[i]=a[i]-mi;
    		}
    		for(int i=1; i<=n; i++) {
    			pre[i]=pre[i-1]+b[i];
    		}
    		for(int i=L; i<=n; i++) {//一边找最小的前缀和,一边进行运算;这个也关键!
    			mins=min(pre[i-L],mins);
    			if(pre[i]-mins>=0) {
    				k=1;
    				l=mi;
    				break;
    			}
    		}
    		if(!k)
    			r=mi;
    	}
    	r=r*1000;
    	printf("%d\n",(int)r);
    	return 0;
    }
    
    • 1

    信息

    ID
    1019
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者