codeforce 939 E. Maximize!(贪心)

本文解析了一个算法竞赛题目,探讨了如何通过贪心算法解决特定类型的查询问题,包括元素插入和查询最大值与平均值的问题。
E. Maximize!
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a multiset S consisting of positive integers (initially empty). There are two kind of queries:

  1. Add a positive integer to S, the newly added integer is not less than any number in it.
  2. Find a subset s of the set S such that the value  is maximum possible. Here max(s) means maximum value of elements in s — the average value of numbers in s. Output this maximum possible value of .
Input

The first line contains a single integer Q (1 ≤ Q ≤ 5·105) — the number of queries.

Each of the next Q lines contains a description of query. For queries of type 1 two integers 1 and x are given, where x (1 ≤ x ≤ 109) is a number that you should add to S. It's guaranteed that x is not less than any number in S. For queries of type 2, a single integer 2 is given.

It's guaranteed that the first query has type 1, i. e. S is not empty when a query of type 2 comes.

Output

Output the answer for each query of the second type in the order these queries are given in input. Each number should be printed in separate line.

Your answer is considered correct, if each of your answers has absolute or relative error not greater than 10 - 6.

Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if .

Examples
input
Copy
6
1 3
2
1 4
2
1 8
2
output
0.0000000000
0.5000000000
3.0000000000
input
Copy
4
1 1
1 4
1 5
2
output
2.0000000000

题意:给出n个操作,操作1往集合中插入元素x,操作2查询答案

查询的答案为所有子集中 max(最大元素-平均值)


分析:首先是贪心考虑什么情况下查询所得最大,肯定是只选一个最大值,然后一直选较小值使得平均数减小

根据题目,我们可以发现随着元素的插入,所查询的答案是递增的(因为没有删除操作,原有的答案一定可以找出一个子集包含),此时所得的答案就可以从原有的答案中得来(可以这样考虑,比如当前最大值是max1,然后又插入了个比它大的max2,前面所求得的子集对max1而言都可以使平均数减小,那么max2更是如此),所以每次查询时用到的数可以直接删除,然后每次根据新加入的数字不断更新即可,具体看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>t;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    ll n,x,op,maxx=0,num=0,sum=0;
    double ans=0;
    scanf("%lld",&n);
    while(n--)
    {
        scanf("%lld",&op);
        if(op==1)
        {
            scanf("%lld",&x);
            if(!t[x])q.push(x),maxx=max(maxx,x);
            t[x]++;
        }
        else
        {
            ans=max(ans,maxx-(maxx+sum)*1.0/(num+1));//直接利用之前最优的子集
            while(!q.empty())//求得当前最优子集
            {
                x=q.top();
                q.pop();
                if(maxx-(maxx+sum+t[x]*x)*1.0/(t[x]+num+1)>ans)
                {
                    ans=maxx-(maxx+sum+t[x]*x)*1.0/(t[x]+num+1);
                    sum+=t[x]*x;
                    num+=t[x];
                    t[x]=0;
                }
                else
                {
                    //没用到该元素,后面比它大的元素肯定不会再用到
                    q.push(x);
                    break;
                }
            }
            printf("%.6f\n",ans);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值