浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

AtCoder Tenka1 Programmer Beginner Contest 解题报告

赛时写了ABC,D实在没啥思路,然后C又难调...然后就从写完AB时的32名掉到了150+名

T_T

码力不够,思维不行,我还是AFO吧

比赛链接

A - Measure

sb模拟,奇数串倒着输出偶数串正着输出

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {
    
    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010

char s[ N ] ;

int main() {
    scanf( "%s" , s + 1 ) ;
    int len = strlen( s+1 ) ;
    if( len == 2 ) puts( s + 1 ) ;
    else {
        for( int i = len ; i ; i -- ) putchar( s[ i ] ) ;
    }
}
View Code

B - Exchange

还是模拟...按着题意的要求来就好,奇数一种情况偶数一种情况

然后一边$+\frac{1}{2}$,一边$-\frac{1}{2}$就好

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {
    
    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010
int a[ 3 ] , k ;

int main() {
    in2( a[ 1 ] , a[ 0 ] ) ; in1( k ) ;
    for( int i = 1 ; i <= k ; i ++ ) {
        if( a[ i % 2 ] % 2 ) a[ i % 2 ] -- ;
        a[ ( i % 2 ) ^ 1 ] += a[ i % 2 ] / 2 ;
        a[ i % 2 ] -= a[ i % 2 ] / 2 ;
    }
    out( a[ 1 ] ) , putchar(' ') , outn( a[ 0 ] ) ; 
}
View Code

C - Align

很恶心的分类讨论

首先要知道一个结论,最中间的数一定是最大或者最小的,然后我们可以在旁边依次填入最大/次大/最小/次小的数

对串的奇偶分开讨论(取mid的不同)

然后对于中间填最大还是填最小也要分开讨论

然后综合几种情况取个最优就行

写的有点长,实际上应该不用这么多代码的QAQ

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {
    
    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010

int n ;
int b[ N ] ;
int a[ N ] ;
ll ans = 0 ;

int main() {
    in1( n ) ;
    for( int i = 1 ; i <= n ; i ++ ) in1( a[ i ] ) ;
    sort( a+1 , a+n+1 ) ;
    int l = 1 , r = n , mid = ( l + r ) >> 1 ; 
    if( n % 2 ) {
        b[ mid ] = a[ r -- ] ;
        for( int i = mid - 1 ; i ; i -- ) {
            if( ( mid - i ) % 2 ) b[ i ] = a[ l ++ ] , b[ mid + mid - i ] = a[ l ++ ] ;
            else b[ i ] = a[ r -- ] , b[ mid + mid - i ] = a[ r -- ] ;
        }
        ll sum = 0 ;
        for( int i = 2 ; i <= n ; i ++ ) sum += abs( b[ i ] - b[ i - 1 ] ) ;
        ll t = sum ;
        l = 1  , r = n ;
        b[ mid ] = a[ l ++ ] ;
        for( int i = mid - 1 ; i ; i -- ) {
            if( ( mid - i ) % 2 == 0 ) b[ i ] = a[ l ++ ] , b[ mid + mid - i ] = a[ l ++ ] ;
            else b[ i ] = a[ r -- ] , b[ mid + mid - i ] = a[ r -- ] ;
        }
        sum = 0 ;
        for( int i = 2 ; i <= n ; i ++ ) sum += abs( b[ i ] - b[ i - 1 ] ) ;
        printf( "%lld\n" , max( t , sum ) ) ;
        return 0 ;
    }
    b[ mid ] = a[ r -- ] ;
    b[ mid + 1 ] = a[ l ++ ] ;
    for( int i = mid - 1 ; i ; i -- ) {
        if( ( mid - i ) % 2 ) b[ i ] = a[ l ++ ] , b[ n - i + 1 ] = a[ r -- ] ;
        else b[ i ] = a[ r -- ] , b[ n - i + 1 ] = a[ l ++ ] ;
    }
    ll sum = 0 , t = 0 ;
    for( int i = 2 ; i <= n ; i ++ ) {
        sum += abs( b[ i ] - b[ i - 1 ] ) ;
    }
    t = sum ;
    l = 1 , r = n ;
    b[ mid + 1 ] = a[ r -- ] ;
    b[ mid ] = a[ l ++ ] ;
    for( int i = mid - 1 ; i ; i -- ) {
        if( ( mid - i ) % 2 == 0 ) b[ i ] = a[ l ++ ] , b[ n - i + 1 ] = a[ r -- ] ;
        else b[ i ] = a[ r -- ] , b[ n - i + 1 ] = a[ l ++ ] ;
    }
    sum = 0 ;
    for( int i = 2 ; i <= n ; i ++ ) {
        sum += abs( b[ i ] - b[ i - 1 ] ) ;
    }
    printf( "%lld\n" , max( sum , t ) ) ; 
}
View Code

D - Crossing

写这题之前一定要先读懂题意

我比赛时一直读错题意,到结束时脑子里想的还是错误的题意....然后就炸了

令k为所选子集的数量。

任何两个子集的交集大小为1,并且为1,2,...,N中的任何一个元素也使用了两次

对于选出来的子集的限制就是这样的

我们不妨把这些子集抽象成点,交集抽象成边,于是$1-n$这些元素就是边的种类

那么不难看出整个图有$\frac{k(k-1)}{2}$条边,并且边的数目要等于n

于是可以枚举出来这个k先,qzz大佬好像推了一个式子$O(1)$求出了这个k,不过我数学比较菜就直接枚举了T_T

然后如果这个k枚举不出来就说明无解(一个比较玄学的地方,我从1枚举到n来判会WA掉第一个点,其他都没问题,然后从1枚举到500就没问题,不知道是怎么回事)

然后来连边

因为每个元素要沟通两个子集

所以类似于完全图那样连边就好

int x = 0 ;
for( int i = 0 ; i < k ; i ++ ) {
    for( int j = i + 1 ; j < k ; j ++ ) {
        x ++ ;
        s[ i ].push_back( x ) ;
        s[ j ].push_back( x ) ;
    }
}

然后就没了

所以说这题的主要难度在于读懂题意T_T

#include <bits/stdc++.h>

#define ll long long
#define inf 0x3f3f3f3f 
#define il inline 

#define in1(a) a=read()
#define in2(a,b) in1(a),in1(b)
#define in3(a,b,c) in2(a,b),in1(c)
#define in4(a,b,c,d) in2(a,b),in2(c,d)
#define out(a) printf( "%d" , a ) 
#define out_(a) printf( " %d" , a )
#define outn(a) out(a),putchar('\n')

#define I_int int 
inline I_int read() {

    I_int x = 0 , f = 1 ; char c = getchar() ;
    while( c < '0' || c > '9' ) {
        if( c == '-' ) f = -1 ;
        c = getchar() ;
    }
    while( c >= '0' && c <= '9' ) {
        x = (x << 1) + (x << 3) + c - 48 ;
        c = getchar() ;
    }
    return x * f ;
}
#undef I_int

using namespace std ;

#define N 100010

int n , k ;

vector<int>s[N]; 

int main() {
    in1( n ) ;
    k = -1 ;
    for( int i = 1 ; i < 500 ; i ++ ) 
        if( i * ( i - 1 ) / 2 == n ) { k = i ; break ; }
    if( k == -1 ) { return puts("No"),0; }
    int x = 0 ;
    for( int i = 0 ; i < k ; i ++ ) {
        for( int j = i + 1 ; j < k ; j ++ ) {
            x ++ ;
            s[ i ].push_back( x ) ;
            s[ j ].push_back( x ) ;
        }
    }
    puts("Yes"); outn(k);
    for( int i = 0 ; i < k ; i ++ ) {
        out((int)s[i].size());
        int len = s[ i ].size();
        for( int j = 0 ; j < len ; j ++ ) {
            out_(s[i][j]);
        }
        putchar('\n');
    }
    return 0 ;
}
View Code

 

还是太菜,还是要继续努力啊QAQ

posted @ 2018-10-30 22:16  henry_y  阅读(388)  评论(0编辑  收藏  举报