题目描述
给定一个长度为 n 的非负整数序列 A ,求一个平均数最大的,长度不小于 L 的子段。
输入格式
第一行用空格分隔的两个整数 n 和 L;
第二行为 n 个用空格隔开的非负整数,表示 Ai。
输出格式
输出一个整数,表示答案的 1000 倍。不用四舍五入,直接输出。
样例
样例输入
10 6
6 4 2 10 3 8 5 9 4 1
样例输出
6500
数据范围与提示
1≤n≤10^5, 0≤Ai≤2000。
二分结果,判定“是否存在一个长度不小于L的子序列,平均数不小于二分的值”。
将数列中每个数都减去二分的值,就转化为判定“是否存在一个长度不小于L的子序列,子序列的和非负”。
可利用前缀和的思想求解最大子序列。
AC代码:
CSDN博客:https://blog.csdn.net/qq_40889820
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<cstring>
#include<iomanip>
#include<vector>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<map>
#define mem(a,b) memset(a,b,sizeof(a))
#define e 2.71828182
#define Pi 3.141592654
#define INF 1<<30
using namespace std;
int n,L;
double a[100010],sum[100010];
//将数列中每个数都减去二分的值,判定“是否存在一个长度不小于L的子序列,子序列的和非负”。
bool islegal(double mid)
{
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i]-mid;
double min_val=INF,ans=-INF;
for(int i=L;i<=n;i++)
{
min_val=min(min_val,sum[i-L]);
ans=max(ans,sum[i]-min_val);
}
return ans>=0.0;
}
int main()
{
cin>>n>>L;
mem(sum,0);
for(int i=1;i<=n;i++) cin>>a[i];
double l=-1e6,r=1e6;
while(r-l>1e-5)
{
double mid=(l+r)/2;
if(islegal(mid)) l=mid;
else r=mid;
}
cout<<int(r*1000);
}