4502. 集合操作(双指针)(有详细过程)

输入样例1:

6
1 3
2
1 4
2
1 8
2

输出样例1:

0.000000
0.500000
3.000000

输入样例2:

4
1 1
1 4
1 5
2

输出样例2:

2.000000

    首先数据范围为5*10^5,一般来说时间复杂度到10^9就会超时,因此本题的时间复杂度应该为n*logn

    应该是一个边输入边处理的题目(纯第一自觉)

来分析一下题目:

        (1):所得序列是非递减序列

        (2):求序列S:max(s)-mean(s)

mean(s)要尽量小,max(s)要尽量大,这时来分析两者之间的关系

        易知S集合应该除max(s)以外尽量取最小的数,因此S应该是从  下标0开始到k的的元素加一个其它值

         设max1>max2;

求:max1(s)-mean1(s)-max2(s)+mean2(s);

max1-max2+\frac{\sum_{0,k}^{}+max2}{k+1}-\frac{\sum_{0,k}^{}+max1}{k+1}   

可知恒大于0

则max(s)应该取队尾(因为队尾元素最大)

现在来考虑 0到k子集该如何选

          首先用k和n来做头尾指针

          每一次插入元素时n都会后移,

          当每一次插入元素后往k+1位运算一下,如果(a[n]-\frac{a_{k+1}+\sum_{0,k+a[n]}^{}}{k+2})-(a[n]-\frac{\sum_{0,k+a[n]}^{}}{k+1})>0的话就++k;

k+1是因为还要计算包括max(s)在内的k+1个元素和的平均数

代码:

#include<iostream>
using namespace std;
const int N=5e5+10;
int a[N];
int main()
{
    int m;
    int k=0,n=0;
    double res,sum;//sum为前k位的和
    scanf("%d",&m);
    while(m--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&a[++n]);
            while(k+1<n&&a[k+1]<(a[n]+sum)/(k+1))sum+=a[++k];//
            res=a[n]-(sum+a[n])/(k+1);
            
            
        }else printf("%lf\n",res);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值