前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【题解】平均数

【题解】平均数

作者头像
MikeC
发布2022-09-21 14:56:26
1.5K0
发布2022-09-21 14:56:26
举报
文章被收录于专栏:MikeC's Blog

题目描述

给一个长度为 n 的数列,我们需要找出该数列的一个子串,使得子串平均数最大化,并且子串长度 \ge m

输入格式

第一行两个整数 nm

接下来 n 行,每行一个整数 a_i,表示序列第 i 个数字。

输出格式

一个整数,表示最大平均数的 1000 倍,如果末尾有小数,直接舍去,不要用四舍五入求整。

输入输出样例

输入 #1

代码语言:javascript
复制
10 6
6
4
2
10
3
8
5
9
4
1

输出 #1

代码语言:javascript
复制
6500

说明/提示

  • 对于 60\% 的数据,保证 m\le n\le 10^4
  • 对于 100\% 的数据,保证 1 \leq m\le n\le 10^50\le a_i\le2000

分析

显然这是一个“最小值最大”的问题,所以我们要通过二分来枚举平均值,再寻找字段和较大的字段,代入平均值判断是否成立,不成立则将右端向左,成立则将左端向右,使两个端点不断相互逼近最优解即可得到答案。

代码

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
int n,m;
double a[100001],sum[100001],b[100001];
double eps=1e-5,l=-1e6,r=1e6;
double min(double x,double y){
    if(x>y)return y;else return x;
}
double max(double x,double y){
    if(x<y)return y;else return x;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    while(r-l>eps){
        double mid = (l+r)/2;
        double maxx=-1e10,minn=1e10;
        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];
        for(int i=m;i<=n;i++){ 
            minn=(double)min(minn,sum[i-m]);
            maxx=(double)max(maxx,sum[i]-minn);
        }
        if(maxx>0)l=mid;else r=mid;
    }
    cout<<int(r*1000);
    return 0;
} 

最后修改:2021 年 07 月 05 日 09 : 07 PM

© 允许规范转载

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021 年 07 月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 输入格式
  • 输出格式
  • 输入输出样例
    • 输入 #1
      • 输出 #1
      • 说明/提示
      • 分析
      • 代码
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档