hdu 2993 MAX Average Problem

斜率dp,主要是结合求下凸包的性质

#include <STDIO.H>
#include <STRING.H>
#include <algorithm>
using namespace std;
/*
	dp[i] = max{(sum[i]-sum[j])/(i-j) } (i-j >= k)
	等于点(i,sum[i])与点(j,sum[j])间的斜率

	斜率dp
	每次更新i时,更新凸包
*/
const int MAXN = 100005;
inline double max(double a, double b)
{
	return a>b?a:b;
}
double sum[MAXN];
int q[MAXN];
double input()
{
	char c;
	double res = 0.0;
	do 
	{
		c = getchar();
	} while ( c < '0' || c > '9');

	do 
	{
		res = res*10 + (c - '0');
		c = getchar();
	} while ( c >= '0' && c <= '9');
	return res;
}
double cross(int a, int b, int c)
{
	return (sum[b]-sum[a])*(c-a) - (sum[c]-sum[a])*(b-a);
}
int main()   
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
	int n, k;
	int i, j;
	int head;
	while (scanf("%d%d", &n, &k) == 2)
	{
		sum[0] = 0.0;
		for (i = 1; i<= n; ++i)
			sum[i] = sum[i-1]+input();
		double res = 0, tp;
		head = 0;
		q[head++] = 0;	// 从0开始
		for (i = k; i<= n; ++i)
		{
			j = i-k;	// 更新最短距离处的点
			while (head>1 && cross(q[head-2],q[head-1],j)>0)
				--head;
			q[head++] = j;
			// 二分寻找最大值
			int mid;
			int a, b;
			a = 0, b = head-1;
			while (a < b)
			{
				mid = (a+b)>>1;
				if (cross(q[mid],q[mid+1],i) > 0)
					b = mid;
				else
					a =mid+1;
			}
			tp = (sum[i]-sum[q[a]])/(i-q[a]);
			res = max(res, tp);
		}
		printf("%.2lf\n", res);
	}
	return 0;
}


你可能感兴趣的:(hdu 2993 MAX Average Problem)