杭电2993 && POJ2018(斜率dp)

MAX Average Problem

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)

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

思路:

题意:给定一个长度为n的数字序列,求长度大于等于 k 的平均值最大的连续子序列。

方法:

  • 斜率dp
  • sum[i]表示:前i个数和
  • 分子:sum[j] - sum[k]
  • 分母:j - k

注意:

  • 要自己写输入函数
  • 杭电上保留小数点后两位
  • POJ上不执行四舍五入,直接将结果乘以1000
  • 输出时要将 double 类型的 ans 转换为 int 类型的 a
  • POJ提交代码要选择G++
在杭电上始终超时,POJ上不超时。

POJ上的AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
#define maxn 100010
int sum[maxn];//前i个数和 
int a[maxn];//输入的数 
int q[maxn];//队列 

double up(int j,int k)//分子 
{
    return sum[j]-sum[k];
}

double down(int j,int k)//分母 
{
    return j-k;
}

int input()//自己写输入函数 
{
    char ch=' ';
    while(ch<'0'||ch>'9')
    {
        ch=getchar();
    }
    int x=0;
    while(ch<='9'&&ch>='0')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}

int main()
{
    int head,tail;//队头队尾 
    int n,k;
    double ans;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        sum[0]=0;
        ans=0;
        for(int i=1;i<=n;i++)
        {
            a[i]=input();//输入数 
            sum[i]=sum[i-1]+a[i];//前i项和 
        }
        head=tail=0;
        q[tail++]=0;
        for(int i=k;i<=n;i++)
        {
            while(head+1<tail && up(i,q[head])*down(i,q[head+1])<=up(i,q[head+1])*down(i,q[head]))
            {
                head++;
            }
            ans=max(ans,up(i,q[head])/down(i,q[head]));
            int tmp=i-k+1;
            while(head+1<tail && up(tmp,q[tail-1])*down(q[tail-1],q[tail-2])<=up(q[tail-1],q[tail-2])*down(tmp,q[tail-1]))
            {
                tail--;
            }
            q[tail++]=tmp;
        }
        ans*=1000;
        int a=ans;//要注意 
        printf("%d\n",a);
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值