首先如果序列为奇数,那么可以考虑枚举中位数,但是如果序列为偶数呢,这个如果枚举的话一定超时,但是又没什么好的办法,那么就证明一下答案序列一定为奇数
图片来自Visors(懒得手敲了好麻烦):
有了上述证明,那么我们枚举每个数作为中位数,在能取到的情况下,每次同时取
k
k
k个比它大的和
k
k
k比它小的组成序列
但是如果这里仍然枚举的话,时间复杂度仍是 O ( n 2 ) O(n^2) O(n2),过不了
首先假设中位数为 a m a_m am,已经取了比它小的最小的 a 1 a_1 a1和最大的 a n a_n an,那么平均数为:
a 1 + a m + a n 3 \frac{a_1 + a_m + a_n }{3} 3a1+am+an
加下来我们尝试再加入一组数 a 2 , a n − 1 a_2,a_{n-1} a2,an−1,平均数为:
a 1 + a 2 + a m + a n − 1 + a n 5 = a 1 + a m + a n 3 ∗ 3 5 + a 2 + a n − 1 5 \frac{a_1 + a_2+ a_m + a_{n-1}+a_n }{5}=\frac{a_1+ a_m +a_n }{3}*\frac{3}{5}+\frac{a_2+ a_{n-1} }{5} 5a1+a2+am+an−1+an=3a1+am+an∗53+5a2+an−1
因此不难观察到平均数每次的增量应该是越来越小且可能会变为负增量,而中位数是不变的,那么答案应该是先递增后递减的
或者这样,由于每加入一组数的和是递减的,而除数是递增的,那么如果列出函数图像的话,应该是一个凸函数图像,这种函数关系显然需要三分查找解决
PS:在判断 a b > c d \frac{a}{b} > \frac{c}{d} ba>dc时,没必要转化为浮点数,直接判断 a ∗ d > b ∗ c a*d>b*c a∗d>b∗c即可
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <cstdio>
#include <string>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int Mod=1e9+7;
const int maxn=1e6+10;
int n;
int a[maxn];
ll sum[maxn];
ll f(int i){
return sum[i]+sum[n]-sum[n-i];
}
double solve(int x,int pos){
int l=1,r=min(pos-1,n-pos);
while(l+10<r){
int midl=l+(r-l)/3;
int midr=r-(r-l)/3;
if((f(midl)+x)*(2*midr+1)>(f(midr)+x)*(2*midl+1)) r=midr;
else l=midl;
}
double ans=0.0;
for(int i=l;i<=r;i++)
ans=max(ans,(double)(f(i)+x)/(2*i+1)-x);
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
double ans=0.0;
for(int i=1;i<=n;i++){
ans=max(ans,solve(a[i],i));
}
printf("%.2f\n",ans);
return 0;
}