ybt1679子集

1679:子集

时间限制: 1000 ms 内存限制: 262144 KB

【题目描述】

定义一个可重数集的价值:集合中所有数的平均数减去它们的中位数。

现在给出\(n\)个数\(a_i\),请你找出这\(n\)个数中的一个非空子集,使这个子集的价值最大。

【输入】

第一行一个整数\(n\)表示数字个数。

第二行\(n\)个整数\(a_i\)

【输出】

仅一行一个实数表示答案,结果保留5位小数。

【输入样例】

6
2 3 3 5 7 8

【输出样例】

1.66667

【样例解释】

最优子集为3,3,8。

【数据规模】

对于20%的数据,\(n≤20\)

对于60%的数据,\(n≤2000\)

对于100%的数据,\(n≤2×10^5,0≤a_i≤10^6\)


这个题目不好想,看了题解才明白!
很一个问题很好想,那就是:答案>=0。明显,如果小于0,那还不如随便选两个,那答案就是0。
所以,如果价值最大的子集有偶数个数,那么$$\dfrac{\sum_{i=1}^{2n} {a_i}}{2n}>=\dfrac{a_n+a_{n+1}}{2}$$
如果价值最大的子集有奇数个数,那么$$\dfrac{\sum_{i=1}^{2n-1} {a_i}}{2n-1}>=a_n$$
第二个问题,就不好想了,那就是:价值最大的子集数字一定是奇数个。
如果是偶数(2n)个,那么去掉第n+1个,那个得到的价值更大!
证明:
\((\dfrac{\sum_{i=1}^{2n} {a_i}-a_{n+1}}{2n-1}-a_n)-(\dfrac{\sum_{i=1}^{2n} {a_i}}{2n}-\dfrac{a_n+a_{n+1}}{2})\)
\(=\dfrac{2n\sum_{i=1}^{2n} {a_i}-2na_{n+1}-2n(2n-1)a_n-(2n-1)\sum_{i=1}^{2n} {a_i}+n(2n-1)(a_n+a_{n+1})}{2n(2n-1)}\)
\(=\dfrac{\sum_{i=1}^{2n} {a_i}-n(2n-1)a_n+n(2n-3)a_{n+1}}{2n(2n-1)}\)
因为\(\dfrac{\sum_{i=1}^{2n} {a_i}}{2n}>=\dfrac{a_n+a_{n+1}}{2}\)
也就是\(\sum_{i=1}^{2n} {a_i}>=na_n+na_{n+1}\)
所以上面的等式
\(>=\dfrac{na_n+na_{n+1}-n(2n-1)a_n+n(2n-3)a_{n+1}}{2n(2n-1)}\)
\(=\dfrac{2n(1-n)a_n+2n(n-1)a_{n+1}}{2n(2n-1)}\)
\(=\dfrac{2n(n-1)(a_{n+1}-a_n)}{2n(2n-1)}\)
\(=\dfrac{(n-1)(a_{n+1}-a_n)}{2n-1}\)
\(>=0\)
所以去掉\(a_{n+1}\)价值更大。

这样问题就变成了,我们枚举中间的数(也就是中位数)和前后数的个数,来求最大价值。为了价值最大,所以中们数前后的数都要最大的,也就是排序后,中位数后面的要最后面的,前面的要紧挨着中位数的。

然后,我们发现中位数是定值,所以价值由平均数决定。而平均数要加上中位数,所以随着前后数的增加平均数会出现一个单峰,我们要求的就是最大值,这就用到了三分!!

由于是整数,三分时,最后三个数要单独算!

哎,总算是完成了!
不好做!!!


#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n,sz[maxn];
long long sm[maxn];
double ans=0;
double f(int c,int pos)
{
	return double(sm[n]-sm[n-c]+sm[pos]-sm[pos-1-c])/(c+c+1);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%d",&sz[i]);
	sort(sz+1,sz+1+n);
	for(int i=1;i<=n;++i)sm[i]=sm[i-1]+sz[i];
	for(int i=2;i<n;++i)
	{
		int cd=min(i-1,n-i);
		int l=1,r=cd;
		while(r-l>=3)
		{
			int lm=l+(r-l)/3,rm=r-(r-l)/3;
			if(f(lm,i)<f(rm,i))l=lm;
			else r=rm;
		}
		ans=max(ans,max(f(l,i),max(f(r,i),f((l+r)/2,i)))-sz[i]);
	}
	printf("%.5lf",ans);
	return 0;
}

posted on 2025-01-08 22:37  gryzy  阅读(36)  评论(0)    收藏  举报

导航