codeforce 939E 差分+二分/三分

传送门:http://codeforces.com/problemset/problem/939/E

题意:

有两种操作:

(1)在集合S中插入一个元素

(2)输出最大的 Max(s)mean(s) M a x ( s ) − m e a n ( s ) ——其中s是集合的子集,Max(s)表示s中最大的元素,mean(s)表示s的平均值

(3) 输入保证插入的元素比原集合中的所有元素都要大

分析:

(1)有一个前提条件:所选的最优的集合s必然包含集合S中最大的元素,其他元素必然是S的一个前缀

(2)函数 Max(s)mean(s) M a x ( s ) − m e a n ( s ) 有极值

(3)对于有极值的函数考虑用二分或者三分的思路求解

题解(二分思路):

mi=anan+i1j=0aji+1 m i = a n − a n + ∑ j = 0 i − 1 a j i + 1

mi+1mi m i + 1 − m i = an+i1j=0ajai(i+1) a n + ∑ j = 0 i − 1 a j − a i ( i + 1 ) (此处去除了分母,因为分母对于函数的正负号没有影响,而二分过程只与函数的正负号有关,故可以去除分母)

f(i)=mi+1mi f ( i ) = m i + 1 − m i

可以用前一项减去后一项来证明证明 f(i) f ( i ) 是非递减的

二分找到最小的 i i 使得 f(i)<=0 Max(s)mean(s) M a x ( s ) − m e a n ( s ) 取得最大值

代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

long long sum[500005];
long long a[500005];
int main()
{
    int q;
    cin>>q;
    int cnt=0;
    memset(a,0,sizeof a);
    memset(sum,0,sizeof sum);
    double ans=0;
    while(q--)
    {
        int op;
        cin>>op;
        if(op==1)
        {
            cin>>a[cnt];
            int l=0,r=cnt;
            if(cnt>=1)
                sum[cnt]=sum[cnt-1]+a[cnt];
            else
                sum[cnt]=a[cnt];
            while(l<r)
            {
                int mid=(l+r)/2;
                long long fi;
                if(mid!=0)
                    fi=a[cnt]+sum[mid-1]-a[mid]*(mid+1);
                else
                    fi=a[cnt]-a[mid]*(mid+1);
                if(fi<=0) r=mid;
                else l=mid+1;
            }
            double avg=1.0*(sum[r-1]+a[cnt])/(r+1);
            double tmp=a[cnt]-avg;
            ans=max(ans,tmp);
            cnt++;
        }else{
            printf("%.10f\n",ans);
        }
    }
    return 0;
}

三分思路:不做差分,直接找函数的最大值,网上的题解大多为三分,故不做详细分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值