Codeforces 931 C. Laboratory Work

http://codeforces.com/problemset/problem/931/C

 

题意:

给定一个数列,要求构造一个等长的数列,使得数列的平均值等于给定数列,并且使得构造出的数列中与原数列相同的数字个数最小,输出最小相同数字个数与构造的数列。
数列长度不超过100000,给定数列中最大的数字与最小的数字相差不超过2。

要求构造出的数列中最大值与最小值不能大于或小于原数列中的最大值与最小值。

 

如果最大-最小=0,那只能使用原数列

如果最大-最小=1,也还是只能使用原数列

如果最大-最小=2

要么把每2个次大的改成一个最小和一个最大,要么把一个最大和一个最小改成2个次大

两种情况取最优

 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 100001

int a[N];

void read(int &x)
{
    x=0; int f=1; char c=getchar();
    while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    x*=f;
}

int main()
{
    int n;
    read(n);
    for(int i=1;i<=n;++i) read(a[i]);
    sort(a+1,a+n+1);
    if(a[n]-a[1]<=1) 
    {
        printf("%d\n",n);
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
        return 0;
    }
    int s1=0,s2=0,s3=0;
    for(int i=1;i<=n;++i)
    {
        if(a[i]==a[1]) s1++;
        else if(a[i]==a[n]) s3++;
        else s2++;
    }
    int t=min(s1,s3),k=s2/2;
    int m=a[1];
    if(t>k)
    {
        for(int i=1;i<=t;++i) a[i]=m+1;
        for(int i=1;i<=t;++i) a[n-i+1]=m+1;        
        printf("%d\n",n-t*2);
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
    }
    else
    {
        for(int i=1;i<=k;++i) a[s1+i*2-1]=m,a[s1+i*2]=m+2;
        printf("%d\n",n-k*2);
        for(int i=1;i<=n;++i) printf("%d ",a[i]);
    }
}

 

posted @ 2018-03-05 10:14  TRTTG  阅读(438)  评论(0编辑  收藏  举报