CF 939E-Maximize! (三分法)

#题目链接
http://codeforces.com/problemset/problem/939/E
#题意简述
现在有一个数列,一开始为空,有两种操作。
1.加入一个数,保证这个数比之前的数都要大
2.在这个数列中选择一个子集S,使得S中的最大元素减掉S的平均值最大,输出这个最大值
#做法
首先,每次加入一个数,有两种可能,一种是最大值不变,第二种是以当前加入的这个数为最大值。
以当前这个数为最大值,那么我们就希望平均值尽量的小,显然我们从前往后取,计算平均值,当什么时候平均值要开始变大了我们就停止。然后你发现这个平均值的函数是个开口向上的单峰函数,所以我们只要三分求出这个函数的最小值就行了,然后更新一下答案。

#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<iostream>
#include<cmath>
#define LL long long
#define INF (2139062143)
#define N (500001)
using namespace std;
int Q,cnt,x,opt;
LL sum[N],a[N];
double maxans;
template <typename T> void read(T&t) {
	t=0;
	bool fl=true;
	char p=getchar();
	while (!isdigit(p)) {
		if (p=='-') fl=false;
		p=getchar();
	}
	do {
		(t*=10)+=p-48;p=getchar();
	}while (isdigit(p));
	if (!fl) t=-t;
}
double calc(int x){
	return (sum[x]+a[cnt])/(1.0*(x+1));
}
int main(){
	read(Q);
	while (Q--){
		read(opt);
		if (opt==2){
			printf("%.10lf\n",maxans);
		} 
		if (opt==1){
			read(x);
			a[++cnt]=x;
			sum[cnt]=sum[cnt-1]+x; 
			int l=1,r=cnt-1;
			double ans=1e9;
			while (l<=r){
				if (r-l<=3){
					ans=calc(r);
					for (int i=l;i<r;i++) ans=min(ans,calc(i));
					break;
				}
				int mid1=l+(r-l)/3,mid2=mid1+(r-l)/3;
				if (calc(mid1)>calc(mid2)) l=mid1;
				else r=mid2;
			}
			//printf("ans %.10lf\n",ans);
			maxans=max(maxans,x-ans);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值