追梦算法----Best Cow Fences

题目描述

原题来自:USACO 2003 Mar. Green

给定一个长度为 n 的非负整数序列 A ,求一个平均数最大的,长度不小于 L 的子段。

输入格式

第一行用空格分隔的两个整数 n 和 L;

第二行为 n 个用空格隔开的非负整数,表示 Ai​。

输出格式

输出一个整数,表示这个平均数的 1000 倍。不用四舍五入,直接输出。

样例

输入数据 1

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

Copy

输出数据 1

6500

Copy

数据范围与提示

1≤n≤10^5,0≤Ai​≤2000。

反思总结:

这道题是二分题

看到题目所给的数据和求字段的内容,我是怎么也不会想到用二分的方法来做这道题的。

按照正常的思路是先确定子段长度,再确定子段,然后再求平均值。这样的作法肯定是超时的。

这道题是使用二分的方法来缩小平均值得范围,这个方法的厉害之处在于,可以使用平均数值的大小确定子段的范围。

解题先知:如何判断平均数是大还是小:

令数列的每个数都减去现在的平均值,将的到的值相加,得到的和如果大于 0 就说明平均数小了,反之,则平均数大了,需要缩小一点。

1、将每一个数减去平均值的差保存下来。

2、将的到的差,通过前缀和优化。

3、从后面往前面枚举结尾的前缀和,通过在前面找最小的前缀和,然后相减就能得到当前子段差的前缀和。

4、判断差是否大于 0 。大于 0 就说明平均数小了,反之,则平均数大了,需要缩小一点。

需要注意:

一旦找到比 0 大的字段,马上就能进行平均值范围的变化了,不需要等到循环完才改变范围。

因为无论后面有没有比这个值大的子段,程序都会判断一次的,所以不需要非要找到最大的,只需要找到大的就可以了。 

一般求子段可以使用前缀和来优化。这个精度的问题我也没注意到。

求子段和的时候,一边找最小前缀和,一边进行运算也是没有想到!

#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;
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Fences是一个用于整理和排布电脑桌面图标的软件。首先,你需要下载和安装Fences免费软件,并确保你的系统符合要求(Windows XP/Vista/7)。 一旦安装完成,你可以按照以下步骤使用Fences: 1. 打开Fences软件。在桌面上,你将看到一个默认的"Fence",它是一个用于组织图标的容器。 2. 可以通过拖动桌面上的图标来将其放入Fence中。你可以创建多个Fence来组织不同类别的图标。 3. 如果你想创建一个新的Fence,只需在桌面上点击右键,选择"Fences",然后点击"Create New Fence"。这将在桌面上创建一个新的Fence。 4. 你还可以自定义Fence的属性。右键点击Fence,选择"Configure Fence"。在这里,你可以更改Fence的名称、颜色和透明度等。 5. 如果你不再需要某个Fence,可以将其删除。右键点击Fence,选择"Delete Fence"。这将删除该Fence以及其中的图标。 总的来说,Fences可以帮助你快速整理桌面图标,并将其分组显示,使得你的桌面更加整洁和有序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【经验分享】F e n c e s 桌面布局软件(Win All)----中文免费版+教程](https://blog.csdn.net/qq_51237779/article/details/127546142)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [Fences -让你的桌面图标分组显示,成块状化](https://blog.csdn.net/alex197963/article/details/4806096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值