Codeforces Round #251 (Div. 2)

今天cf太凶残,各种hack狂魔.. 18hack简直sxbk .. 相比之下我的-1hack就是个笑话委屈

A. Devu, the Singer and Churu, the Joker

题意 : 一个人唱歌,一个人讲笑话,唱歌的人每唱一首歌至少要休息10分钟,讲笑话的不用休息,而且每个笑话5分钟。两个人表演的时间最多只能d,给你唱歌的人唱的每首歌的时间长度,问你最多可以将多少个笑话。如果唱歌的人歌都唱不完,那就输出-1

思路 : 反正讲笑话不会影响唱歌的休息...所以就贪心的能唱歌就唱歌就行了


#include<stdio.h>

int main(){
    int n , d ;
    while( scanf( "%d%d" , &n , &d ) != EOF ) {
        int cnt = 0 ;
        int time = 0 ;
        bool flag = 0 ;
        for( int i = 0 ; i < n; i ++ ) {
            int a  ;scanf( "%d" , &a ) ;
            if( time + a <=d ) {
                time += a ;
            }else{
                flag = 1 ;
            }
            if( time + 10 <= d ) cnt += 2 ;
            else if( time + 5 <= d ) cnt += 1 ;
            time += 10 ;
        }
        if( flag == 1 ) {
            puts( "-1" ) ;
        }else{
            if( d >= time ) cnt += ( d - time ) / 5 ;
            printf( "%d\n" , cnt ) ;
        }
    }
    return 0 ;
}

B. Devu, the Dumb Guy

题意 : 给你n门课,每门课有ci章,你可以任意安排上课的顺序,上第一门课,每章花x分钟,第二门课每章花x-1分钟 ... 另外每章花费时间最少为1分钟

思路 : 直接做 , 注意别溢出 , 不然会被hack狂魔光顾的

#include <stdio.h>
#include <algorithm>
using namespace std;

__int64 a[100005] , n , x , ans ;

int main(){
    while( scanf( "%I64d%I64d" , &n , &x ) != EOF ) {
        ans = 0 ;
        for( int i = 1 ;i <= n; i ++ ) scanf( "%I64d" , &a[i] ) ;
        sort( a + 1 , a + 1 + n ) ;
        for( int i = 1 ; i <= n; i ++ ) {
            ans += x * a[i] ;
            if( x > 1 )
                x -- ;
        }
        printf( "%I64d\n" , ans ) ;
    }
    return 0 ;
}

C. Devu and Partitioning of the Array

题意 : 给你n个整数 , 你需要分成k份,并且有p份和为偶数 ,可以就输出YES以及任意方案, 不行输出NO

思路 : 首先我们要统计奇数有多少个 , 假设为odd个,如果odd < k - p 那么必然是NO , 因为不可能凑到 k - p 个和为奇数的堆 。 然后剩下的奇数必然要两两配对 , 所以 odd - ( k - p ) 必须是偶数 , 然后最后我们要配出 p 个偶数堆 , 所以 ( odd - ( k - p ) ) / 2 + n - odd 至少要是p个 。这样构造完之后,剩下全部放第一堆就行了。实现的时候要注意细节,最后挂了很多人

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std;

int a[100005] ;
deque<int> Odd , Even ;
vector<int> ans[100005] ;

int main(){
    int n , k , p ;
    while( scanf( "%d%d%d" , &n , &k , &p ) != EOF ) {
        int odd = 0 ;
        for( int i = 0 ; i < k ; i ++ ) ans[i].clear() ;

        Odd.clear() ; Even.clear() ;
        for( int i = 1 ;i <= n ; i ++ ) {
            scanf( "%d" , &a[i] ) ;
            if( a[i] % 2 == 1 ) {
                odd ++ ;
                Odd.push_back( a[i] )  ;
            }else{
                Even.push_back( a[i] ) ;
            }
        }
        int even = n - odd ;
        if( odd < k - p ) {
            puts( "NO" ) ;
            continue ;
        }
        int t = odd - k + p ;
        if( t % 2 == 1 ) {
            puts( "NO" ) ;
            continue ;
        }
        if( t / 2 + even < p ) {
            puts( "NO" ) ;
            continue ;
        }
        puts( "YES" ) ;
        for( int i = 0 ;i < k - p ; i ++ ) {
            int tmp = *Odd.begin() ; Odd.pop_front() ;
            ans[i].push_back( tmp ) ;
        }
        int i ;
        for( i = k - p ; i < k && Even.size() ; i ++ ) {
            int tmp = *Even.begin() ; Even.pop_front() ;
            ans[i].push_back( tmp ) ;
        }
        if( i < k ) {
            for( ; i < k ; i ++ ) {
                int tmp = *Odd.begin() ; Odd.pop_front() ;
                ans[i].push_back( tmp ) ;
                tmp = *Odd.begin() ; Odd.pop_front() ;
                ans[i].push_back( tmp ) ;
            }
            int size = Odd.size() ; 
            for( int i = 0 ; i < size ;i ++ ) {
                int tmp = *Odd.begin() ; Odd.pop_front() ;
                ans[0].push_back( tmp ) ;
            }
        }else{
            int size = Odd.size() ; 
            for( int i = 0 ; i < size ;i ++ ) {
                int tmp = *Odd.begin() ; Odd.pop_front() ;
                ans[0].push_back( tmp ) ;
            }
            size = Even.size() ;
            for( int i = 0 ; i < size ;i ++ ) {
                int tmp = *Even.begin() ; Even.pop_front() ;
                ans[0].push_back( tmp ) ;
            }
        }
        for( int i = 0 ; i < k ; i ++ ) {
            printf( "%d" , ans[i].size() ) ;
            for( int j = 0 ; j < ans[i].size() ; j ++ ) {
                printf( " %d" , ans[i][j] ) ;
            }
            puts( "" ) ;
        }
    }
    return 0 ;
}

D. Devu and his Brother

题意 : 给你两个数组,你每次可以是任意一个数组中的一个元素减一或者加一 , 你要让第一个数组的最小值大于等于第二个数组的最大值。

思路 : 其实我们要求的是一个K,使得第一个数组中小于K的都变成K ,第二个数组中大于K的都变成K ,并且加减的和是最小的。我们可以很容易得到一个结论,这个K必然是原本来个数组中的一个数。

证明 : 首先 , 我们很容易就能排序K大于两个数组中所有的数和小于数组中所有数的情况。只需要讨论存在 A < K < B 并且 A ,B 属于两个原来的数组

假如 K 不属于原本的两个任意一个数 , 那么a数组中有ka个数小于K , b数组中kb个数大于K , 那么假设 Ka = Kb , 那么K取A和B的值是不会变的。那么如果Ka 大于 Kb , 那么选择A会较优 , 反之选择B会较优。

所有最优的K一定是原来数组中数字。

那么直接枚举两个数组中的数字即可 , 计算的话通过预处理之后,每个K只要O(1)就能求出,所以总的只要O(n)

这题还可以三分之类,写的时候没想那么多

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

__int64 a[100005] , b[100005] ;
__int64 suma[100005] , sumb[100005] ;
__int64 ans ;

int main(){
    int n , m ;
    while( scanf( "%d%d" , &n , &m ) != EOF ) {
        ans = 0x3f3f3f3f3f3f3f ;
        for( int i = 1 ; i <= n ; i ++ )
            scanf( "%I64d" , &a[i] ) ;
        for( int i = 1; i <= m; i ++ ) 
            scanf( "%I64d" , &b[i] ) ;
        sort( a + 1 , a + 1 + n ) ;
        sort( b + 1 , b + 1 + m ) ;
        for( int i = 1 ;i <= n; i ++ ) {
            suma[i] = suma[i-1] + a[i] ;
        }
        for( int i = m ; i >= 1 ; i -- ) {
            sumb[i] = sumb[i+1] + b[i] ;
        }
        int ii = 1 , jj = 1 ; 
        for( ii = 1 ; ii <= n ; ii ++ ) {
            for( ; jj <= m ; jj ++ ) {
                if( b[jj] >= a[ii] ) break;
            }
            __int64 cost = 0 ;
            cost = ( ii - 1 ) * a[ii] - suma[ii-1] + ( sumb[jj] - ( m - jj + 1 ) * a[ii] ) ;
            ans = min( ans , cost ) ;
        }
        ii = n , jj = m ;
        for( jj = m ; jj >= 1 ; jj -- ) {
            for( ; ii >= 1 ; ii -- ) {
                if( a[ii] <= b[jj] ) break;
            }
            __int64 cost = 0 ;
            cost = ii * b[jj] - suma[ii] + ( sumb[jj] - ( m - jj + 1 ) * b[jj] ) ;
            ans = min( ans , cost ) ;
        }
        printf( "%I64d\n" , ans ) ;
    }
    return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值