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;
}