Codeforces 626E Simple Skewness(暴力枚举+二分)
E. Simple Skewness
time limit per test:3 seconds
memory limit per test:256 megabytes
input:standard input
output:standard output
Define the simple skewness of a collection of numbers to be the collection's mean minus its median. You are given a list of n (not necessarily distinct) integers. Find the non-empty subset (with repetition) with the maximum simple skewness.
The mean of a collection is the average of its elements. The median of a collection is its middle element when all of its elements are sorted, or the average of its two middle elements if it has even size.
Input
The first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of elements in the list.
The second line contains n integers xi (0 ≤ xi ≤ 1 000 000) — the ith element of the list.
Output
In the first line, print a single integer k — the size of the subset.
In the second line, print k integers — the elements of the subset in any order.
If there are multiple optimal subsets, print any.
Examples
Input
4
1 2 3 12
Output
3
1 2 12
Input
4
1 1 2 2
Output
3
1 1 2
Input
2
1 2
Output
2
1 2
Note
In the first case, the optimal subset is
, which has mean 5, median 2, and simple skewness of 5 - 2 = 3.
In the second case, the optimal subset is
. Note that repetition is allowed.
In the last case, any subset has the same median and mean, so all have simple skewness of 0.
题目链接:http://codeforces.com/contest/626/problem/E
题意
给出n个数的集合,求一个 (平均数-中位数)最大 (偏度最大)的子集,输出子集元素个数和各个元素(任意顺序)。
分析
因为是子集,所以不一定是连续的序列。然后我们有下面几个结论。
1.最大偏度一定≥0
因为一个元素时,偏度为0。
2.最大偏度子集必定有元素个数为奇数个的。
证:
如果当元素个数是偶数2*k时偏度最大,我们证明它去掉一个元素a[k+1]不会更差。
子集里排好序分别是a[i]。除去a[k+1]其它数的平均值为av
新平均值-旧平均值=av-(av+a[k+1])/2=(av-a[k+1])/2
新中位数-旧中位数=a[k]-(a[k]+a[k+1])/2=(a[k]-a[k+1])/2
且有 旧平均值-旧中位数=(av+a[k+1])/2-(a[k]+a[k+1])/2=(av-a[k])/2≥0 (否则不可能偏度最大)
所以有 平均值增量-中位数增量=(av-a[k])/2≥0
所以新的偏度肯定不会更差。
3.平均值先递增后递减
因为是奇数个,所以枚举每个数做中位数,假如左右延伸长度为j,那么要使偏度更大,我们一定是每次选剩下的里面左边最大和右边最大的数。所以剩下的数越来越小,平均值增加得越来越少,而当前平均值越来越大,到某个峰值后平均值就开始减小了。
所以可以用二分法每次取中点和中点旁边一个点判断当前平均值在增加还是减小,增加就往右找,减小就往左找。
顺便吐槽一句:cf测评机不行啊,跑这个跑了大半个小时才跑完!!!
下面给出AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int N=200020;
5 inline int read()
6 {
7 int x=0,f=1;
8 char ch=getchar();
9 while(ch<'0'||ch>'9')
10 {
11 if(ch=='-')
12 f=-1;
13 ch=getchar();
14 }
15 while(ch>='0'&&ch<='9')
16 {
17 x=x*10+ch-'0';
18 ch=getchar();
19 }
20 return x*f;
21 }
22 int n;
23 ll s[N<<1],a[N<<1];
24 int ansi=1,ansp;
25 double ans;
26 //最大偏度≥0,所以初始值就是只有第一个元素,偏度为0
27 ll sum(int i,int j)
28 {
29 return s[n]-s[n-j]+s[i]-s[i-j-1];
30 }
31 int main()
32 {
33 n=read();
34 for(int i=1;i<=n;i++)
35 cin>>a[i];
36 sort(a+1,a+1+n);
37 for(int i=1;i<=n;i++)
38 {
39 s[i]=s[i-1]+a[i];
40 }
41 for(int i=2;i<n;i++)
42 {
43 int l=1,r=min(i-1,n-i),m;
44 ll s1,s2;
45 while(l<r)
46 {
47 int mid=(l+r)/2;
48 s1=sum(i,mid)*(2*mid+3);
49 s2=sum(i,mid+1)*(2*mid+1);
50 if(s1>s2)
51 {
52 r=mid;
53 }
54 else
55 {
56 l=mid+1;
57 if(s1==s2)
58 break;
59 }
60 }
61 if(1.0*sum(i,l)/(2*l+1)-a[i]>ans)
62 {
63 ans=1.0*sum(i,l)/(2*l+1)-a[i];
64 ansi=i;
65 ansp=l;
66 }
67 }
68 cout<<ansp*2+1<<endl;
69 cout<<a[ansi]<<" ";
70 for(int i=1;i<=ansp;i++)
71 {
72 cout<<a[ansi-i]<<" "<<a[n-i+1]<<" ";
73 }
74 cout<<endl;
75 return 0;
76 }
- redis学习教程之一基本命令
- 在java中使用redis
- springmvc学习笔记--json--返回json的日期格式问题
- springmvc学习笔记--mybatis--使用插件自动生成实体和mapper
- velocity的一些用法
- String.split()用法以及特殊分隔符注意,ps:|
- Mybatis在idea中错误:Invalid bound statement (not found)
- java字符编码和oracle乱码
- ehcache报错
- java继承覆盖与向上转型,权限
- java变量的加载顺序
- java类的初始化和对象的创建顺序
- 附近的人位置距离计算方法
- java中复制对象通过反射或序列化
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python从URL获取图片、读取图片格式并保存到本地
- Linux一键屏蔽指定国家所有的IP访问
- React基础(9)-React中发送Ajax请求以及Mock数据
- 一个快速引入CDN的workflow
- 在Ryzen平台上安装macOS High Sierra苹果系统
- v-selectpage 基于Vue2的高清重制版
- Android Studio3.6中的View Binding初探及用法区别
- Android日志文件的读写工具类
- <Go语言学习笔记>【数组与切片】
- Android Studio 3.6 新特性一览(推荐)
- 03 Linux下的SVN服务器搭建
- Android openGl 绘制简单图形的实现示例
- 解决Android studio 3.6.1 出现Cause: unable to find valid certification path to requested target 报错的问题
- 使用kotlin实现MVP的方式(简单好用)
- Android Studio 3.6中新的视图绑定工具ViewBinding 用法详解