题意:
有一个集合S,进行Q次操作。
第一种操作:在集合S中添加元素x,保证x不小于S中的任何元素。
第二种操作:选出一个S的子集s,让max(s)-mean(s)最大(max(s)表示这个子集的最大值,mean(s)表示这个子集的平均数),输出这个最大值。
思路:
经过多次举例,可以知道s中,当前的最大值一定是要选的,因为这个权重比较大,然后对于这个平均值,可以再举例分析。
肯定是从左往右取,比如1 3 5 8 9,假如取1,则平均值为5,加入3,则平均值为4.333,加入5,则平均值为4.5,加入8,则平均值为5.2,加入的过程用到前缀和。
举例大法好。
由此可见,平均值一个凹函数,要求得这个最小值,三分一下就可以啦。
所以答案就是max(s)-这个最小值。
代码:
ll a[500010];
ll pre[500010];
int num;
double Calc(int x)
{
return 1.0*(pre[x]+a[num])/(x+1);
}
int main()
{
int q,ope;
scanf("%d",&q);
pre[0]=0;
num=0;
while(q--)
{
scanf("%d",&ope);
if(ope==1)
{
num++;
scanf("%lld",&a[num]);
pre[num]=pre[num-1]+a[num];
}
else
{
int l=1,r=num;
double ans=min(Calc(l),Calc(r));
while(l<r)
{
int mid=(l+r)>>1;
int rmid=(mid+r)>>1;
double t1=Calc(mid),t2=Calc(rmid);//若求最大值则>,min取max
if(t1>t2) l=mid;
else r=rmid;
ans=min(ans,min(t1,t2));
}
printf("%.15f\n",1.0*a[num]-ans);
}
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!