题意:求给n个数的序列求最大的连续k个数的平均值
题解:n很大肯定不能一个一个试所有但是是我们发现(pre[i]-pre[j])/(i-j)如果把i,j看着横坐标pre[i],pre[j]看做纵坐标的话就是求斜率了,然后此时可以用斜率优化一下如下图
然后我们就可以在去头的是当队列的第二个满足第一个图的条件就可以去掉队列头,在加入i的时候如果i满足第二个图的条件就可以把对尾去掉了
最后要加入读入挂优化如果不加的会超时
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long int ll;
const int mx = 1e5+5;
ll pre[mx];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline bool _read(ll &sum){
char ch=nc();
if(ch==EOF)
return 0;
sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
deque<int>q;
void erase_front(int i){
while(q.size()>=2){
int a = q.front();
q.pop_front();
int b = q.front();
if((pre[i]-pre[b])*(i-a)<(pre[i]-pre[a])*(i-b)){
q.push_front(a);
return;
}
}
}
void insert(int i){
while(q.size()>=2){
int a = q.back();
q.pop_back();
int b = q.back();
if((pre[i]-pre[b])*(a-b)>(pre[a]-pre[b])*(i-b)){
q.push_back(a);
break;
}
}
q.push_back(i);
}
int main(){
ll n,m;
pre[0] = 0;
while(_read(n)&&_read(m)){
for(int i = 1; i <= n; i++){
_read(pre[i]);
pre[i]+=pre[i-1];
}
while(!q.empty())
q.pop_back();
double ans = 0;
q.push_back(0);
int j = 1;
for(int i = m; i <= n; i++){
erase_front(i);
int a = q.front();
ans = max(ans,1.0*(pre[i]-pre[a])/(i-a));
insert(j++);
}
printf("%.2f\n",ans);
}
return 0;
}