[CF626E]Simple Skewness
题目
题解
令 \(len\) 为选出数列长度,首先,我们需要证明,\(len\) 为偶数情况的一定劣于 \(len\) 为奇数的情况
假设这个差最大的子集中有偶数个元素,那么去掉中间较大的元素后对平均数减小的影响比对中位数的减小影响小,所以最后的解更优了,所以最后的集合的元素数量一定是奇数。
那么,我们现在已经确定 \(len\) 为奇数的情况是最优,所以我们只需用 \(\mathcal O(n)\) 的复杂度枚举中位数的位置,然后,我们再三分数列长度的一半 \(len\),最后的长度即为 \(len\times 2+1\)
至于为什么这个偏度值对于 \(len\) 是单峰的,此处给出证明:
设数列中位数为 \(m\),比 \(m\) 小的前 \(x\) 个数为 \(f(x)\),数列最大的前 \(x\) 个数为 \(g(x)\),那么,数列的最优偏度值为 \(p=\frac{f(x)+g(x)+m}{2x+1}-m\),再设数列变长 \(\Delta\),那么变长后的数组偏度值为 \(p'=\frac{f(x+\Delta)+g(x+\Delta)+m}{2x+1+2\Delta}-m\)
那么
\[\begin{aligned} p-p'&=\frac{f(x)+g(x)+m}{2x+1}-m-\left\{ \frac{f(x+\Delta)+g(x+\Delta)+m}{2x+1+2\Delta}-m \right \} \\ &=\frac{f(x)+g(x)+m}{2x+1}-m-\left\{ \frac{f(x)+\sum_{i=x+1}^{x+\Delta}a[i]+g(x)+\sum_{i=1}^\Delta a[i]+m}{2x+1+2\Delta}-m \right \} \\ &=\left [ f(x)+g(x)+m \right ](2x+2\Delta+1)-\left [ f(x)+g(x)+m+\sum_{i=x+1}^{x+\Delta}a[i]+\sum_{i=1}^\Delta a[i]\right ](2x+1) \\ &=2\Delta\left [ f(x)+g(x)+1\right ]-(2x+1)\left [\sum_{i=1}^\Delta(a[i]+a[x+i])\right ] \end{aligned} \\ \]当 \(\Delta\) 变大时,前一部分随 \(\Delta\) 等倍变大,而后者会随着 \(\Delta\) 的变大,刚开始会增加得很快,之后越来越小,即 \(p-p'\) 随 \(x\) 变大,先变大后变小,所以 \(p'\) 随 \(x\) 变大,先变大后变小,即证明是单峰
三分这个长度 \(len\),然后算答案即可
代码
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i<=i##_end_;++i)
#define fep(i,__l,__r) for(signed i=(__l),i##_end_=(__r);i>=i##_end_;--i)
#define erep(i,u) for(signed i=tail[u],v=e[i].to;i;i=e[i].nxt,v=e[i].to)
#define writc(a,b) fwrit(a),putchar(b)
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
typedef long long LL;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef unsigned uint;
#define Endl putchar('\n')
#define int long long
// #define int unsigned
// #define int unsigned long long
#define cg (c=getchar())
template<class T>inline void read(T& x){
char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
if(f)x=-x;
}
template<class T>inline T read(const T sample){
T x=0;char c;bool f=0;
while(cg<'0'||'9'<c)f|=(c=='-');
for(x=(c^48);'0'<=cg&&c<='9';x=(x<<1)+(x<<3)+(c^48));
return f?-x:x;
}
template<class T>void fwrit(const T x){//just short,int and long long
if(x<0)return (void)(putchar('-'),fwrit(-x));
if(x>9)fwrit(x/10);
putchar(x%10^48);
}
template<class T>inline T Max(const T x,const T y){return x>y?x:y;}
template<class T>inline T Min(const T x,const T y){return x<y?x:y;}
template<class T>inline T fab(const T x){return x>0?x:-x;}
inline int gcd(const int a,const int b){return b?gcd(b,a%b):a;}
inline void getInv(int inv[],const int lim,const int MOD){
inv[0]=inv[1]=1;for(int i=2;i<=lim;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
}
inline LL mulMod(const LL a,const LL b,const LL mod){//long long multiplie_mod
return ((a*b-(LL)((long double)a/mod*b+1e-8)*mod)%mod+mod)%mod;
}
const int MAXN=200000;
const double INF=1e9+5;
int a[MAXN+5],n;
LL pre[MAXN+5];
inline void Init(){
n=read(1);
rep(i,1,n)a[i]=read(1);
sort(a+1,a+n+1);
rep(i,1,n)pre[i]=pre[i-1]+a[i];
}
inline double calc(const int p,const int len){
double average=pre[p]-pre[p-len-1]+pre[n]-pre[n-len];
average/=(len<<1|1);
return average-a[p];
}
inline pair<double,int> trisearch(const int p,const int L,const int R){
int l=L,r=R,p1,p2;
while(l+2<r){
p1=l+(r-l+1)/3,p2=r-(r-l+1)/3;
if(calc(p,p1)>calc(p,p2))r=p2;
else l=p1;
}
pair<double,int>ret=mp(0,0);
double res;
rep(i,l,r){
res=calc(p,i);
if(res>ret.first){
ret=mp(res,i);
}
}return ret;
}
inline void Solve(){
double maxx=-INF;
pair<double,int>ret;
pii ans=mp(0,0);
rep(i,1,n){
ret=trisearch(i,0,Min((LL)i-1,n-i));
if(ret.first>maxx){
maxx=ret.first;
ans=mp(i,ret.second);
}
}
int p=ans.first,len=ans.second;
writc(len<<1|1,'\n');
rep(i,p-len,p)writc(a[i],' ');
rep(i,n-len+1,n)writc(a[i],' ');
}
signed main(){
Init();
Solve();
return 0;
}