Maximize!
题 意:给你q个询问,两种操作,1.每次往容器里面加入一个x,保证x一定大于容器里面所有的数。2.输出容器里面的一个子集,求最大的子集的MAX - avg最大。
数据范围:
1<=q<=5e5
1<=x<=1e9
输入样例:
6
1 3
2
1 4
2
1 8
2
输出样例:
0.0000000000
0.5000000000
3.0000000000
思 路:首先这是一个凸函数,这个很好想,我们需要找的就是凸函数的那个MAX点,然后三分就好了。
具体写一下三分的思路
也就是一个lmid和一个rmid把l,r等分成三份。
对于凸函数,如果f(lmid) > f(rmid) 的话 那么max一定在l到rmid之间,如果f(lmid) < f(rmid)那么max就一定实在lmid 到r之间。
下面来考虑一下凹函数。
如果f(lmid) > f(rmid)的话那么min肯定在r,lmid之间,如果f(rmid) < f(lmid)那么肯定是在l,rmid之间。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5+5;
ll sum[maxn];
int a[maxn];
int q,total;
double f(int x){
return (double)a[total-1] - (double)(sum[x]+a[total-1])/(double)(x+1);
}
int main(){
scanf("%d",&q);
total = 1;
while(q--){
int ch,x;
scanf("%d",&ch);
if(ch == 1){
scanf("%d",&a[total]);
sum[total]= sum[total-1]+a[total];
total++;
}else{
int l = 1,r = total-1;
while(r-l>2){
int mid = l + (r-l)/3;
int mmid= r - (r-l)/3;
if(f(mid) > f(mmid)){
r = mmid;
}else if(f(mid) < f(mmid)){
l = mid;
}else{
r = mmid;
l = mid;
}
}
double MAX = 0;
for(int i=l;i<=r;i++){
MAX = max(MAX,f(i));
}
printf("%.10f\n",MAX);
}
}
return 0;
}