HDU 2993

MAX Average Problem

Problem Description
Consider a simple sequence which only contains positive integers as a1, a2 ... an, and a number k. Define ave(i,j) as the average value of the sub sequence ai ... aj, i<=j. Let’s calculate max(ave(i,j)), 1<=i<=j-k+1<=n.
 

Input
There multiple test cases in the input, each test case contains two lines.
The first line has two integers, N and k (k<=N<=10^5).
The second line has N integers, a1, a2 ... an. All numbers are ranged in [1, 2000].
 

Output
For every test case, output one single line contains a real number, which is mentioned in the description, accurate to 0.01.
 

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

Sample Output
  
  
6.50
 

一道简单的斜率优化。用sum数组存放和,sum[i]为a[1]~a[i]的和,要求(sum[i]-sum[j])/(i-j)的最大值(i-j>=k)。

要用到输入挂,不然会超时。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int maxn=100005;
int sum[maxn];
int q[maxn];

namespace fastIO
{
#define BUF_SIZE 100000
bool IOerror=0;
inline char nc()
{
    static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
    if(p1==pend)
    {
        p1=buf;
        pend=buf+fread(buf,1,BUF_SIZE,stdin);
        if(pend==p1)
        {
            IOerror=1;
            return -1;
        }
    }
    return *p1++;
}

inline bool blank(char ch)
{
    return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}

inline void read(int &x)
{
    char ch;
    while(blank(ch=nc()));
    if(IOerror)
        return ;
    for(x=ch-'0'; (ch=nc())>='0'&&ch<='9'; x=x*10+ch-'0');
}
#undef BUF_SIZE
}

int main()
{
    int n,k;
    while(fastIO::read(n),!fastIO::IOerror)
        //while(~scanf("%d%d",&n,&k))
    {
        fastIO::read(k);
        sum[0]=0;
        for(int i=1; i<=n; i++)
        {
            int a;
            fastIO::read(a);
            //a = GetInt();
            sum[i]=sum[i-1]+a;
        }
        int head=0,tail=0;
        double ans=0;
        for(int i=k; i<=n; i++)
        {
            int j=i-k;
            while(head+1<tail)//维护下凸性
            {
                int x1=j-q[tail-1];
                int x2=j-q[tail-2];
                int y1=sum[j]-sum[q[tail-1]];
                int y2=sum[j]-sum[q[tail-2]];
                if((ll)x1*y2>=(ll)y1*x2)
                    tail--;
                else
                    break;
            }
            q[tail++]=j;
            while(head+1<tail)//维护上凸性
            {
                int x1=q[head+1]-q[head];
                int x2=i-q[head+1];
                int y1=sum[q[head+1]]-sum[q[head]];
                int y2=sum[i]-sum[q[head+1]];
                if((ll)x1*y2>=(ll)y1*x2)
                    head++;
                else
                    break;
            }
            double tmp=1.0*(sum[i] - sum[q[head]]) / (i - q[head]);
            ans=max(ans,tmp);
        }
        printf("%.2f\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值