• CF626E Simple Skewness


    题目链接

    题目解析

    首先考虑固定一个中位数,来使平均数最大。

    我们可以将这(n)个数排序,然后从中位数的地方左右拓展,根据贪心,大的数肯定是要选的,所以中位数以前中间不会(skip)掉某些数然后选别的,肯定是挨着往前选,而中位数以后肯定是从最大的地方倒着选过来。这个过程中我们发现平均数先变大后变小。这个很好理解:刚开始加入的数都比较大,后来加入的数都越来越小,在某一时刻会使平均数变小。

    那么这是个单峰函数,可以三分加入的数的个数,不过要注意中间可能会出现一段与(x)平行的一段。

    值域是(1e6)级别的,但是我们要相信(cf)优秀的评测速度和它(3s)的时限(雾

    不过可以证明中位数一定在原(n)个数之中,节省掉大量枚举中位数的时间。这个结论换句话说说,也就是选出来的数的个数一定是奇数的时候比较优。

    简单证明:

    不妨设一个奇数长度的答案序列为(a[1...2k-1])(已排序),并且他们的平均数为(av)。现在证明向这个序列中加入一个数,答案不会更优。根据之前的说法,新加入的数如果小于中位数,那么它小于(a[1]);如果它大于中位数,那么它满足(a[k]<=x<=a[k+1]),那么这两种情况在加入有序序列后为(a[0]/a[k+1])

    先讨论(a[k+1])的情况:新的中位数为(frac{a[k]+a[k+1]}2),会变大。而由于这是设的一个答案序列,所以是在中位数为(a[k])的情况下的平均值的最大值,那么(a[k+1])小于平均值,否则它应该在原答案序列中,那么新的平均数会变小。所以答案会变小。

    对于(a[0])的情况:增加(a[0])后,由于(a[0])是一个极小值,所以对平均数的影响要大于对中位数的影响(平均值易受极端值的影响),所以平均值减少得比中位数快,那么答案会变小。

    (怎么感觉都好玄乎,感性理解(2333)

    但其实没有这个结论似乎也不需要枚举完值域,枚举(2n-1)个数就可以了吧(每个数,和每相邻两个数的平均值


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define N 200005
    #define MOD 998244353
    #define INF 0x3f3f3f3f3f3f3f3f
    #define LL long long
    LL rd()
    {
    	LL x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
    	return f*x;
    }
    int n,a[N];
    LL s[N];
    double mx=-INF;
    double f(int pos,int len)
    {
    	LL sum=s[pos]-s[pos-len-1]+s[n]-s[n-len];
    	double av=1.0*sum/(2.0*len+1.0);
    	return av-a[pos];
    }
    pair<double,int> tri(int pos,int l,int r)
    {
    	while(l+3<r)
    	{
    		int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
    		double lans=f(pos,lmid),rans=f(pos,rmid);
    		if(lans<rans) l=lmid;
    		else r=rmid;
    	}
    	pair<double,int> res=make_pair(0,0);
    	
    	for(int i=l;i<=r;i++)
    	{
    		double tmp=f(pos,i);
    		if(tmp>res.first)
    			res=make_pair(tmp,i);
    	}
    	return res;
    }
    int main()
    {
    	n=rd();
    	for(int i=1;i<=n;i++)
    		a[i]=rd();
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++)
    		s[i]=s[i-1]+a[i];
    	
    	pair<int,int> ans=make_pair(0,0);//选一个 为0 (排除掉负数 
    	for(int i=1;i<=n;i++)
    	{
    		pair<double,int> res=tri(i,0,min(i-1,n-i));
    		if(res.first>mx)
    		{
    			mx=res.first;
    			ans=make_pair(i,res.second);
    		}
    	}
    	
    	printf("%d
    ",ans.second*2+1);
    	for(int i=ans.first-ans.second;i<=ans.first;i++)
    		printf("%d ",a[i]);
    	for(int i=n-ans.second+1;i<=n;i++)
    		printf("%d ",a[i]);
    	return 0;
    }
    /*
    
    */
    
  • 相关阅读:
    Mybatis批量插入,是否能够返回id列表
    SVN和Git代码管理小结
    SVN和Git代码管理小结
    Spring异步执行(@Async)2点注意事项
    Spring异步执行(@Async)2点注意事项
    2015年工作中遇到的问题101-110
    Codeforces 263B. Appleman and Card Game
    Codeforces 263A. Appleman and Easy Task
    HDU 482 String
    字符串hash-BKDRHash
  • 原文地址:https://www.cnblogs.com/lyttt/p/14079428.html
Copyright © 2020-2023  润新知