Codeforces 239D:Boring Partition(思维)

本文探讨了一种算法问题,即如何将一组整数通过最优方式分为两个子集,使得两个子集中任选两个不同元素进行特定运算后的最大值与最小值之差达到最小。文章详细介绍了问题背景、解决方案及其实现思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Discription
This problem is the most boring one you’ve ever seen.

Given a sequence of integers a1, a2, …, an and a non-negative integer h, our goal is to partition the sequence into two subsequences (not necessarily consist of continuous elements). Each element of the original sequence should be contained in exactly one of the result subsequences. Note, that one of the result subsequences can be empty.

Let’s define function f(ai, aj) on pairs of distinct elements (that is i ≠ j) in the original sequence. If ai and aj are in the same subsequence in the current partition then f(ai, aj) = ai + aj otherwise f(ai, aj) = ai + aj + h.

Consider all possible values of the function f for some partition. We’ll call the goodness of this partiotion the difference between the maximum value of function f and the minimum value of function f.

Your task is to find a partition of the given sequence a that have the minimal possible goodness among all possible partitions.

Input
The first line of input contains integers n and h (2 ≤ n ≤ 105, 0 ≤ h ≤ 108). In the second line there is a list of n space-separated integers representing a1, a2, …, an (0 ≤ ai ≤ 108).

Output
The first line of output should contain the required minimum goodness.

The second line describes the optimal partition. You should print n whitespace-separated integers in the second line. The i-th integer is 1 if ai is in the first subsequence otherwise it should be 2.

If there are several possible correct answers you are allowed to print any of them.

Examples
Input
3 2
1 2 3
Output
1
1 2 2
Input
5 10
0 1 0 2 1
Output
3
2 2 2 2 2

Note
In the first sample the values of f are as follows: f(1, 2) = 1 + 2 + 2 = 5, f(1, 3) = 1 + 3 + 2 = 6 and f(2, 3) = 2 + 3 = 5. So the difference between maximum and minimum values of f is 1.

In the second sample the value of h is large, so it’s better for one of the sub-sequences to be empty.

题意
给出n个数字和一个常数h,将所有数字分成两组,分别取两数的和的最大值和最小值做差,求出差的最小值,并输出差最小时的分组情况。答案不唯一,输出任意一组即可。
规则:同一组数字相加直接等于数字相加;不同组数字相加等于数字相加再加上h。

思路
这道题看似情况很多,实际上就两种情况。
第一种情况,所有的数字都分成一组,用最大值加次大值的和减去最小值和次小值的和。
第二种情况,将数字分成两组,其中最小值单独一组,再用最大的和减去最小的和,具体看代码。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,h,f;
int a[100010],b[100010];
int min1,min2,min3,max1,max2;
int sum1,sum2;
int main()
{
    cin>>n>>h;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        b[i]=a[i];
    }
    if(n==2)//n为2时只能分成一组
    {
        cout<<0<<endl;
        cout<<1<<" "<<1<<endl;
        return 0;
    }
    sort(b+1,b+1+n);
    min1=b[1];//最小值
    min2=b[2];//次小值
    min3=b[3];//第三小值
    max1=b[n];//最大值
    max2=b[n-1];//次大值
    sum1=max2+max1-min1-min2;//分成一组的情况
    sum2=max(min1+h+max1,max2+max1)-min(min2+min1+h,min3+min2);//分成两组的情况,因为最大值和最小值情况不确定,这里使用max和min函数分别取最大和最小值
    if(sum1<=sum2)
    {
        cout<<sum1<<endl;
        for(int i=1;i<=n;i++)
            cout<<1<<" ";
        return 0;
    }
    cout<<sum2<<endl;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==min1&&f==0)
        {
            cout<<1<<" ";
            f++;//这里要加一个判断,否则与最小值相同的也会分到同一组,我在这个地方WA了至少三遍
        }
        else
            cout<<2<<" ";
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值