HDU 数形结合 2993 MAX Average Problem

来源:互联网 发布:剑三成男痞气捏脸数据 编辑:程序博客网 时间:2024/05/15 08:37

MAX Average Problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5613    Accepted Submission(s): 1389


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 66 4 2 10 3 8 5 9 4 1
 

Sample Output
6.50
 

Source
2009 Multi-University Training Contest 19 - Host by BNU
 

Recommend
chenrui   |   We have carefully selected several similar problems for you:  3401 2829 3415 3530 1513 


题意:给出一个序列,求出在所有长度至少为k的子区间中平均值最大的值。


思路:我们要求的就是 max((sum[i]-sum[j])/(i-j),把对应的(i,sum[i]) 放到坐标系中,发现什么没有?这个表示是一个斜率,就是说求出这些点的最大斜率, 而且可以看出sum是单调递增的。那么我们能用O(n) 的时间求出最大斜率,详细的解答请看《浅谈数形结合思想在信息学竞赛中的应用》,里面说的很详细。。。。 注意,这道题读取的时候用getchar,  会快很多,不然你交去G++会TLE的。


代码:

#include<iostream>#include<cstdio>#include<string.h>#include<cstring>#include<stdio.h>#include<stdlib.h>#include<queue>using namespace std;const int maxn = 100000 + 5;#define LL long longint n, k;int sum[maxn];int q[maxn];inline double max(double a, double b) { return a > b ? a : b; }inline LL up(int i, int j) { return sum[i] - sum[j]; }inline LL down(int i, int j) { return i - j; }void GetInt(int & a){a = 0;char ch;while (ch = getchar() , (ch<'0' || ch>'9'));while ('0' <= ch&&ch <= '9'){a = a * 10 + ch - '0';ch = getchar();}}void input(){sum[0] = 0;for (int i = 1; i <= n; ++i) { GetInt(sum[i]); sum[i] += sum[i - 1]; }}void solve(){int front = 0, rear = 0;q[rear++] = 0;double ans = 0;for (int i = k; i <= n; ++i){int j = i - k + 1;while (rear - front > 1 && up(q[front], i)*down(q[front + 1], i) <= up(q[front + 1], i)*down(q[front], i)) ++front;ans = max(ans, (double)up(i, q[front]) / down(i, q[front]));while (rear - front > 1 && up(q[rear - 1], q[rear - 2])*down(j, q[rear - 1]) > up(j, q[rear - 1])*down(q[rear - 1], q[rear - 2])) --rear;q[rear++] = j;}printf("%.2lf\n", ans);}int main(){while (scanf("%d%d", &n, &k) == 2){input();solve();}}



0 0