codeforces-939E Maximize!

題意
維護一個集合,兩種操作:
1、向集合加入一個數,保證這個數比集合中所有數都大
2、在集合中找一個子集,使子集中最大值減平均值最大,輸出這個最大值
解題思路
加入第ii個數AiAi後,考慮包含AiAi的子集對ansans的影響。
因爲所選子集中最大值已經確定爲AiAi,只需儘可能減小子集中的平均值。
由貪心的思想,一定儘可能選較小的數,即選取的一定爲序列AA的一個前綴,於是暴力方法就是枚舉前綴結束位置jj
由平均數性質,向後枚舉時如果新加入的AjAj小於之前已經加入的數的平均值,則一定拉低平均值,反之會擡高平均值。
由於AA遞增,顯然所得平均值是單峯的,這樣就可以使用三分。
代碼

#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
long long sum[500005];
double ans;
int q,x,num;
inline double check(int w){
	return 1.0*(sum[w]+x)/(w+1);
}
int main(){
	int opt;
	scanf("%d",&q);
while(q--){
	scanf("%d",&opt);
	if(opt==2) {printf("%.8lf\n",ans);continue;}
	scanf("%d",&x);
	int l=1,r=num;
	while(l<r){
		int mid=l+r>>1;
		int midd=mid+r>>1;
		if(mid==midd) midd++;
		double r1=check(mid),r2=check(midd);
		if(r1>r2) l=mid+1;
		else r=midd-1;
	}
	if(l==r) ans=max(ans,1.0*x-1.0*(sum[l]+x)/(l+1));
	sum[++num]=x;sum[num]+=sum[num-1];
}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章