习题:Maximize! (贪心)

题目

传送门

思路

假设我们现在已经有了这个子集的总和为s,个数为siz,最大值为maxx

注意到一个性质

如果\(a_i\le \frac{s}{siz}\),那么\(a_i\)这个元素一定在子集之内

换言之,选的数是连续的

考虑新加入一个元素\(x\),这时最大值发生改变

原来的答案为\(maxx-\frac{s}{siz}\)

现在的答案为\(x-\frac{s-maxx+x}{siz}\)

两式相减可以发现新的答案一定更优

所以子集的最大值一定是整个集合的最大值

代码

#include<iostream>
using namespace std;
int q;
int opt;
int a[1000005];
int lena;
long long s;
int siz;
double basic=1;
int main()
{
	//ios::sync_with_stdio(false);
	scanf("%d",&q);
	for(int i=1;i<=q;i++)
	{
		scanf("%d",&opt);
		if(opt==1)
		{
			lena++;
			scanf("%lld",&a[lena]);
			if(lena==1)
			{
				s=a[lena];
				siz=1;
				continue;
			}
			s-=a[lena-1];
			s+=a[lena];
			for(int j=siz;j<=lena;j++)
			{
				if(s>=1ll*a[j]*siz)
				{
					s+=a[j];
					siz++; 
				}
				else
					break;
			}
		}
		else
		{
			if(lena==0)
				printf("%.10lf\n",0*basic);
			else
				printf("%.10lf\n",a[lena]-basic*s/siz);
		}
	}
	return 0;
}
posted @ 2020-02-06 17:48  loney_s  阅读(97)  评论(0)    收藏  举报