Codeforces 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
题目大意:有一个集合,两种操作:1.往集合里添加一个数,这个数比集合里的所有数都小. 2.求集合的一个子集,使得子集中最大值-平均值尽可能大.
分析:题目说每次插入的数比集合中的数都要小让我想到了二分.
   首先集合中的最大的数x是肯定要选的,因为如果最终选了n个数,那么这个数的贡献就是(n - 1) * x / n.那么现在的任务就是使得平均值尽可能小.很容易想到取尽量多的小数,让平均值最小.但是有数量限制,每次都挑尽量多的小数不一定平均值最小.二分选多少个数?这看不出什么单调性啊......在纸上推一推几个例子,可以发现这其实是一个单峰函数,三分法就好了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;
const double inf = 1e20;

ll q,tot,a[500010],sum[500010],n;

double check(ll x)
{
    if (x == 0)
        return a[n];
    double temp = sum[x] + a[n];
    return temp / (double)(x + 1);
}

int main()
{
    scanf("%I64d",&q);
    while (q--)
    {
        ll id;
        scanf("%I64d",&id);
        if (id == 1)
        {
            ll x;
            scanf("%I64d",&x);
            a[++n] = x;
            sum[n] = sum[n - 1] + a[n];
        }
        else
        {
            
            ll l = 0,r = n,cnt = 0;
            while (l < r && cnt <= 150)
            {
                cnt++;
                ll m1 = l + (r - l) / 3,m2 = r - (r - l) / 3;
                if (check(m1) > check(m2))
                    l = m1;
                else
                    r = m2;
            }
            double ans = inf;
            for (ll i = l; i <= r; i++)
                ans = min(ans,check(i));
            printf("%.10lf\n",a[n] - ans);
        }
    }

    return 0;
}

 

 

 

 

posted @ 2018-02-19 16:18  zbtrs  阅读(268)  评论(0编辑  收藏  举报