1. 程式人生 > >CF939E:Maximize! ——題解

CF939E:Maximize! ——題解

lin ems pac pro 集合 均值 spa 既然 while

http://codeforces.com/problemset/problem/939/E

https://vjudge.net/problem/CodeForces-939E

給一個集合,每次兩個操作:

1 a:將一個大於集合所有數的a添加進集合。

2:查詢集合中所有子集的最大值-平均值的最大值。

有一個結論:最大值所在的子集一定包含集合最大值,我們用感性證明證明一下。

我們假設結論為假,那麽我們已經選定了一個子集,設其最大值為x,我們在集合裏還有一個數為x+1,則如果將x換成x+1,平均值只會加上一個小於1的數,而最大值卻加1,顯然要比原先的值大,所以x+1更優。

同理x與x+2比較可以看成x+1與x+2比較,以此類推。

所以結論必為真。

那麽既然我們能固定一個最大值,我們還有一個顯然成立的結論,就是子集一定為最小的前k個數和最大的數x構成。因為太顯然了就不證了。

既然這樣,那麽顯然答案是一個單峰函數,可以三分求解。

(第一次碰這個題的時候前幾個步驟都想到了三分楞是沒想到……我是真的蠢,看樣子題刷少了)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef double dl;
typedef long long ll;
const int Q=5e5+5
; ll sum[Q],maxx; int len=0; inline dl suan(int k){ return 1.0*(maxx*k-sum[k])/(k+1); } dl sanfen(int l,int r){ int mid1,mid2; while(l<=r){ if(r-l<3){ dl ans=suan(r); for(int i=l;i<r;i++)ans=max(ans,suan(i)); return ans; } mid1
=l+(r-l)/3,mid2=mid1+(r-l)/3; if(suan(mid1)>suan(mid2))r=mid2; else l=mid1; } } int main(){ int q,op; scanf("%d",&q); while(q--){ scanf("%d",&op); if(op==1){ scanf("%lld",&maxx); sum[++len]=sum[len-1]+maxx; } else printf("%.10lf\n",sanfen(0,len-1)); } return 0; }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

CF939E:Maximize! ——題解