关闭

CodeForce 626E Simple Skewness (贪心+三分)

86人阅读 评论(0) 收藏 举报
分类:

题目:给出n个数字,求出一个子集,使得其平均数与中位数的差值最大。

解析:首先将a[1...n]从大到小排序,在固定中位数的位置后,子集的构成必然是在中位数位置的两侧选取相同个,显然,每侧要尽量选取较大的值。

可以发现,选取的个数与平均数具有凸函数性质,所以通过三分找到临界点。整体复杂度O(nlogn)。

[code]:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 2e5+5;

int n,a[maxn];
int o1,o2;
double ans,s[maxn];

void init(){
    ans = -1e9;
}

double f(int p,int x,int a,int b){
    return (s[x-1]+s[p+x]-s[p]+b)/(2*x+a);
}

void sol(){
    double median;
    int i,j,p1,p2;
    int mid1,mid2,l,r,t1,t2;
    for(i = 0;i < 2*n-1;i++){
        if(i&1) p1=i/2,p2=p1+1,t1=2,t2=a[p1]+a[p2],median=1.0*t2/2.0;
        else p1=p2=i/2,t1=1,t2=a[p1],median=a[p1];
        l = 0,r = min(p1,n-p2);
        while(r-l>2){
            mid1 = l+(r-l)/3;
            mid2 = l+2*(r-l)/3;
            if(f(p2,mid1,t1,t2)>=f(p2,mid2,t1,t2)) r = mid2;
            else l = mid1;
        }
        for(j = l;j <= r;j++){
            if(ans < f(p2,j,t1,t2)-median){
                o1 = i,o2 = j;
                ans = f(p2,j,t1,t2)-median;
            }
        }
    }
    printf("%d\n",2*o2+1+(o1&1));
    for(i = 0;i < o2;i++) printf("%d ",a[i]);
    printf("%d ",a[i=o1/2]);
    if(o1&1) printf("%d ",a[i=o1/2+1]);
    for(j = 0;j < o2;j++) printf("%d ",a[++i]);
}

int main(){
    int i,j;
    scanf("%d",&n);
    for(i = 0;i < n;i++) scanf("%d",&a[i]);
    sort(a,a+n);
    reverse(a,a+n);
    s[0] = a[0];
    for(i = 1;i < n;i++) s[i] = s[i-1]+a[i];
    sol();

    return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:34599次
    • 积分:2530
    • 等级:
    • 排名:第14561名
    • 原创:228篇
    • 转载:8篇
    • 译文:0篇
    • 评论:0条
    文章分类