1. 程式人生 > >Codeforces 939E Maximize! (三分查詢)

Codeforces 939E Maximize! (三分查詢)

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
6
1 3
2
1 4
2
1 8
2
Output
0.0000000000
0.5000000000
3.0000000000
Input
4
1 1
1 4
1 5
2
Output
2.0000000000
題意: 有兩種操作,1.往集合裡面加一個數,這個數比集合裡所有元素都大 2.在該集合取一子集使得子集的價值最大,並輸出價值 價值是該子集中最大的值-這個子集的平均值 下列有t組操作,請你根據按照操作輸出 解析: 這道題想一下,每一次2操作,絕對是從現在的集合裡取最大的元素,然後從左到右延伸(這個集合有序),找使得價值最大的子集 這是貪心。 這樣又因為這個找的過程,這個價值曲線隨下標增大是一個向上突的曲線,所以就需要三分查詢
點選開啟連結
這樣最後輸出10位小數的答案就可以了 還有比較坑的一點是,當三分查詢的元素只剩兩個時,不管大小,他只會預設左邊的元素小,所以這裡需要特殊判斷,就是元素為2個的時候就跳出
#include <bits/stdc++.h>
using namespace std;
typedef long long int lli;
const int MAXN = 5e5+10;

lli sum[MAXN];
lli a[MAXN];
int cnt=0;

double solve(int x)
{
    double ans=(x*a[cnt]-sum[x])*1.0/(x+1);
    return ans;
}

int trisection_search(int left, int right)
{
    // 三分搜尋,找到最優解(求函式最大值下的自變數值)
    int midl, midr;
    while (right>left+1)
    {
        midl = (left + right) / 2;
        midr = (midl + right) / 2;
        // 如果是求最小值的話這裡判<=即可
        if(solve(midl) >= solve(midr)) right = midr;
        else left = midl;
    }
    if(solve(left)>solve(right))
        return left;
    else
        return right;

}

int main()
{
    int n;
    scanf("%d",&n);
    int y;
    for(int i=0;i<n;i++)
    {
        scanf("%d",&y);
        if(y==1)
        {
            ++cnt;
            scanf("%lld",&a[cnt]);
            sum[cnt]=sum[cnt-1]+a[cnt];

        }
        else
        {
            int xia=trisection_search(1,cnt-1);
            printf("%.10lf\n",solve(xia));
        }
    }
    return 0;
}