Maximize!
题意:不断向集合中插入一个数,且这个数比集合中所有数都大,然后在集合中找一个子集,使得找到的子集中的最大值减去子集的平均值的差最大;
思路:如何选取子集?最后插入的这个数是一定要选的,然后再选小的数,就是一个最大数加上几个用来拉低平均值的小数构成了所需子集;小数一定是从最小值开始连续增加使平均值减小,直到达到一个临界点,再增加自小数平均值就开始增大了,二次函数;
就像班级里拖后腿的学生越多,班级平均成绩越低,因为拖后腿的对平均值不仅没有贡献还降低平均分,当找到某数时,他比平均分大了,就开始为平均分做贡献了;就是三分找这样的位置;
#include <bits/stdc++.h>
using namespace std;
long long a[500010], sum[500010];
int cnt;
double cal(int x){
return a[cnt]*1.0-(sum[x]+a[cnt])*1.0/((x+1)*1.0);
}
int main(){
int Q;
scanf("%d", &Q);
cnt=0;
int op;
sum[0]=0;
while(Q--){
scanf("%d", &op);
if(op==1){
scanf("%lld", &a[++cnt]);
sum[cnt]=sum[cnt-1]+a[cnt];
}
else{
int l=1, r=cnt-1;
if(cnt==1) printf("%.10f\n", 0.0);
else if(cnt==2)printf("%.10f\n", a[2]*1.0-(a[1]+a[2])*1.0/2.0);
else{
int x=1;
while(l<r){
int mid=(l+r)/2;
int midd=(mid+r)/2;
if(cal(mid)<=cal(midd)){
x=mid;
l=mid+1;
}
else{
x=midd;
r=midd-1;
}
}
if(x>1&&x<cnt-1)
printf("%.10f\n", max(max(cal(x), cal(x+1)), cal(x-1)));
else if(x==1)
printf("%.10f\n", max(cal(x), cal(x+1)));
else
printf("%.10f\n", max(cal(x), cal(x-1)));
}
}
}
return 0;
}