zoukankan      html  css  js  c++  java
  • CF Boring Partition

    D. Boring Partition

    其实这就是一道想法题,题意是:给出N个数和一个非负数H,将这N个数分成两个集合,可以有一个集合为空,给出一个计算公式f(i,j) = a[i] +a[j] (如果i != j && a[i] a[j] 在同一个集合),f(i,j) = a[i] +a[j] +h(i!=j && a[i] a[j] 不在同一个集合里),让你求出一种分法使得f(i,j)中的最大值与最小值的差值最小。

    解题过程:刚开始想的是用两个优先队列,然后从头开始遍历,每次只要和队列中的最大值最小值进行计算就行了,这样一遍就可以找出最值,但是纠结的是不知道初始化怎么办,MAX_F,MIN_F怎么设,将前两个的差值设为最大值和最小值肯定不对,后来看到标签上写的是用排序和贪心,想着排完序之后怎么办,果然这个方向是对的。

    排完序后就可以看出,这个序列有两种情况,一种是所有数字都属于同一个集合,所以这种情况中,F的最大值为a[n]+a[n-1] , 最小值为a[1] +a[2] ,其余的任意两个数的和都在这两个数之间,可以求出一个差值ans1 ,另一种情况就是分成两个集合,这个比较难想点,但是想清楚了也是一种贪心,是如果a[n],a[n-1] 在一个集合里,那么他们两个个和可能最大,如果a[1] ,a[n] 不在一个集合中,那么如果h>a[n-1]-a[1]的话,a[n]+a[1] +h >a[n]+a[n-1] ,至于其他的数,只要在a[1] 和a[n-1] 之间的数都会大于a[n]+a[n-1] ,根据最优分发,它们都要分到a[n]那一个集合中,这样的话才不会产生更大的F,而这种情况下的最小F是,a[1] + a[2] + h , 或者是a[2]  + a[3] ,最后只要判断上面两种情况,哪种产生的差值最小就可以了。

    参考代码:

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <math.h>
    #define  N 100005
    using namespace std ;
    
    int d[N] , a[N] ;
    
    int min( int x , int y )
    {
        return x > y ? y : x ;
    }
    
    int max( int x , int y )
    {
        return x > y ? x : y ;
    }
    
    int main()
    {
        int n , h , f_min1 , f_min2 , i , flag ;
    
        while ( scanf ( "%d%d" , &n , &h ) != EOF )
        {
            for ( i = 1 ; i <= n ; i++ )
            {
                scanf ( "%d" , &d[i] );
                a[i] = d[i] ;
            }
            sort( a + 1 , a + n + 1 ) ;
            f_min1 = ( a[n] + a[n-1] ) - ( a[1] + a[2] ) ;
            f_min2 =  max( a[1] + a[n] + h , a[n] + a[n-1] ) - min( a[1] + a[2] + h , a[2] + a[3] ) ;
            if ( n == 2 || f_min1 <= f_min2 )
            {
                printf ( "%d\n" , f_min1 ) ;
                for ( i = 1 ; i <= n ; i++ )
                {
                    if( i == 1 )
                    printf ( "1" );
                    else
                    printf ( " 1" ) ;
                }
                printf ( "\n" ) ;
            }
            else
            {
                printf ( "%d\n" , f_min2 ) ;
                flag = 0 ;
                for ( i = 1 ; i <= n ; i++ )
                {
                    if ( d[i] == a[1] && !flag )
                    {
                        flag = 1 ;
                        printf ( "2" ) ;
                    }
                    else
                    printf ( "1" ) ;
                    if ( i != n )
                    printf ( " " ) ;
                }
                printf ( "\n" ) ;
            }
        }
        return 0 ;
    }
  • 相关阅读:
    AtCoder Beginner Contest 205
    Codeforces Round #725 (Div. 3)
    Educational Codeforces Round 110 (Rated for Div. 2)【A
    Codeforces Round #722 (Div. 2)
    AtCoder Beginner Contest 203(Sponsored by Panasonic)
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)
    PTA 520 钻石争霸赛 2021
    Educational Codeforces Round 109 (Rated for Div. 2)【ABCD】
    AtCoder Beginner Contest 200 E
    Educational Codeforces Round 108 (Rated for Div. 2)【ABCD】
  • 原文地址:https://www.cnblogs.com/misty1/p/2762226.html
Copyright © 2011-2022 走看看