题意:

有一个集合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 协议 ,转载请注明出处!

ST表 Previous
三分查找 Next