2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Prefer

先给一下结果:
这里写图片描述
单刷被虐成狗,ACM打到怀疑人生,I题的二分答案太丢人了,干脆退竞赛吧!!
233,脸上笑嘻嘻,心里。。。。,这个名次也是够讽刺。
上午校内ACM全场划水,草草地a了三道后,坐观队友debug,结果比赛结束也没A,等比赛结束后花了十分钟debug,就A了,队友异样的眼神。

下午没吃晚饭(午饭就随便吃了点),饿着肚子肝CF的ACM,结果不计rating!!我那么努力地a题,结果什么回报都没有?

累觉不爱。

听完hfu的话后已近开场5分钟了,M题有9个人AC了,瞬间从A题切到M,观察,一个曼哈顿距离。
但是一开始脑子不好使,以为要分类讨论,于是构建模型,hfu教练又来找我讨论仙人掌的故事,我一边回答一遍思考简单做法!!
发现自己智商太低了!!就一水题,此题不放题解,请观察code就行了。

M
#include<bits/stdc++.h>
using namespace std;

template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int xf,yf,xs,ys;
int main(){
    read(xf),read(yf),read(xs),read(ys);
    cout<<abs((xs-1)-xf)+abs((xs+1)-xf)+abs((ys+1)-yf)+abs((ys-1)-yf)+4<<endl;
    //智商受创。
    return 0;
}

然后发现F题也有人做对了,开始认真看F题。
题意归纳一下就是kh->h,u->oo就行了,所有的string能变就变,运用STL里的string函数库中的insert与erase轻松搞定。因为kh->h时以h为主打,倒着来,找到h判前面的字符判定erase更方便(其实都一样)。

#include<bits/stdc++.h>
using namespace std;

template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
set<string> mp;
int n;
int main(){
    string st;
    string ooo="o";
    read(n);
    for(register int i=1;i<=n;i++){
        cin>>st;int len=st.length();
        for(int j=len-1;j>=0;j--){
            while(st[j]=='h'&&st[j-1]=='k')st.erase(j-1,1),j--;
            while(st[j]=='u')st[j]='o',st.insert(j,ooo),j++;
        }
    //  cout<<st<<endl;;
        mp.insert(st);
    }
    cout<<mp.size()<<endl;
    return 0;
}

之后暴怒切了一发I题的二分答案,发现暴力判定是错的,没考虑差值的单调性,这样做随便一组样例就能卡死。然后贡献了一发WA。

赛后才AC的I

还是考虑二分答案。

E

赶紧转战E题(期间谷歌翻译死了一次,网卡了,只能颓QQ,群里大佬A得好快,wsq、wxh他们都要AK了,事实上他们也的确是rank1),思考了一会儿,发现暴力可做,暴力每枚举每一个字符的出现vis。
总之水水就行。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1010;;
template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
bool st[100],dg[26],gf[26];
char cst[100],stm[100],mes[26];
int m,n,tot;
int main(){
    read(n);
    memset(gf,1,sizeof(gf));
    scanf("%s",stm);int len=strlen(stm);
    for(register int i=0;i<len;i++){
        if(stm[i]=='*')st[i]=1;
        else{
            cst[i]=stm[i];
            dg[stm[i]-'a']=1;
        }
    }
    read(m);
    for(register int d=1;d<=m;d++){
        scanf("%s",stm);len=strlen(stm);
        bool sk=0;
        for(register int i=0;i<n;i++){
            if(!st[i]){
                if(stm[i]!=cst[i]){sk=1;break;}
                continue;
            }
            if(dg[stm[i]-'a']){sk=1;break;}
        }
        if(!sk){
            memset(mes,0,sizeof(mes));
            for(register int i=0;i<len;i++){
                if(!st[i])continue;
                mes[stm[i]-'a']=1;
            }
            for(register int i=0;i<26;i++)
                if(!mes[i])gf[i]=0;
        }
    }
    for(register int i=0;i<26;i++)if(gf[i])tot++;
    cout<<tot<<endl;
    return 0;
}
G

G题A得莫名其妙,读完题发现一个暴搜索解决不了两个问(blog主太傻了),所以呢?两个bfs就行了吗!建立边后暴力跑bfs,细节请看code。
vis可以写成bitset更方便统计。

#include<bits/stdc++.h>
using namespace std;
const int N=300105;
struct data{
    int from, to, nxt, pos;
    int tes;
    data(){}
    data(int from,int to,int nxt,int pos,int tes):from(from),to(to),nxt(nxt),pos(pos),tes(tes){}
}E[N<<1];
int head[N],tot,ap[N],cnt,bp[N],n,m,s;
queue<int>que;
int ans;
bool vis[N+55];
inline void adddata(int x,int y,int pos,int tes){
    E[++tot]=data(x,y,head[x],pos,tes),head[x]=tot;
    if(tes==2)E[++tot]=data(y,x,head[y],pos,-tes),head[y]=tot;
}
template<class T>inline void  read(T &res){
    static char ch;T tes=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')tes=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=tes;
}
int t,a,b;
int main(){
    read(n),read(m),read(s);
    memset(ap,-1,sizeof(ap)),memset(bp,-1,sizeof(bp));
    for(register int i=1;i<=m;++i){
        read(t),read(a),read(b);
        if(t!=2)adddata(a,b,0,1);
        else adddata(a,b,++cnt, 2);
    }
    memset(vis,0,sizeof(vis));
    que.push(s);
    vis[s]=1;
    register int u,v;
    while(!que.empty()){
        u=que.front();
        que.pop();
        for(register int c,i=head[u];i;i=E[i].nxt){
            if(v=E[i].to,E[i].tes==1){
                if(!vis[v])vis[v]=1,que.push(v);
            }else{
                if(!vis[v])vis[v]=1,que.push(v),ap[E[i].pos]=E[i].tes<0?0:1;
            }
        }
    }
    ans=0;for(register int i=0;i<=N;++i)if(vis[i])ans++;
    cout<<ans<<endl;
    for(register int i=1;i<=cnt;i++)
        printf("%c",ap[i]?'+':'-');
    putchar('\n');
    memset(vis,0,sizeof(vis));
    que.push(s);
    vis[s]=1;
    while(!que.empty()){
        u=que.front();
        que.pop();
        for(register int i=head[u];i;i=E[i].nxt){
            if(v=E[i].to,E[i].tes!=1)continue;
            if(!vis[v])vis[v]=1,que.push(v);
        }
    }
    ans=0;for(register int i=0;i<=N;++i)if(vis[i])ans++;
    cout<<ans<<endl;
    for(register int i=0;i<tot;i++){
        if(E[i].tes!=1&&E[i].tes>0){
            v=E[i].to,u=E[i].from;
            if(vis[u]&&!vis[v])bp[E[i].pos]=0;
            else bp[E[i].pos] = 1;
        }
    }
    for(register int i=1;i<=cnt; ++i)
        printf("%c",bp[i]?'+':'-');
    putchar('\n');
    return 0;
}
H

找来场外队友?(闲着的wys帮我切H题),这道题全是拼代码量的,基础好code就短,110行也是可以。。。感谢wys先WA一次后让我AC了这道题。(这道题就一个模拟,实在不想写了,还想休息一下呢。)
与上面code完全不一样的code的风格。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std ;

int N , cnt[128] , iss[128] , tots , lef ;
char ss[400005] , out[400005] ;

/*
21
abcdcbaaaaaaaaaaaaaaa
*/
void print(){
    printf( "%d\n" , tots ) ;
    int len = lef / tots / 2 ;//半长串
    for( int i = 48 ; i <= 122 ; i ++ ){
        if( iss[i] ){
            tots -- ; cnt[i] -- ;
            for( int j = 48 , tlen = 0 ; j <= 122 ; j ++ ){
                if( !cnt[j] ) continue ;
                if( len - tlen >= cnt[j]/2 ){
                    cnt[j] /= 2 ;
                    while( cnt[j] ) out[++tlen] = j , cnt[j] -- ;
                } else {
                    while( len - tlen ){
                        out[++tlen] = j ; cnt[j] -= 2 ;
                    }
                    break ;
                }
            }
            for( int j = 1 ; j <= len ; j ++ ) printf( "%c" , out[j] ) ;
            printf( "%c" , i ) ;
            for( int j = len ; j >= 1 ; j -- ) printf( "%c" , out[j] ) ;
            printf( " " ) ;
        }
    }

    for( int i = 1 ; i <= tots ; i += 2 ){
        for( int j = 48 ; j <= 122 ; j ++ ){
            while( cnt[j] ){
                lef -= 2 ; cnt[j] -= 2 ;

                for( int k = 48 , tlen = 0 ; k <= 122 ; k ++ ){
                    if( !cnt[k] ) continue ;
                    if( len - tlen > cnt[k]/2 ){
                        cnt[k] /= 2 ;
                        while( cnt[k] ) out[++tlen] = k , cnt[k] -- ;
                    } else {
                        while( len - tlen ){
                            out[++tlen] = k ; cnt[k] -= 2 ;
                        }
                    }
                }
                for( int k = 1 ; k <= len ; k ++ ) printf( "%c" , out[k] ) ;
                printf( "%c" , j ) ;
                for( int k = len ; k >= 1 ; k -- ) printf( "%c" , out[k] ) ;
                printf( " " ) ;

                for( int k = 48 , tlen = 0 ; k <= 122 ; k ++ ){
                    if( !cnt[k] ) continue ;
                    if( cnt[k] && len - tlen > cnt[k]/2 ){
                        cnt[k] /= 2 ;
                        while( cnt[k] ) out[++tlen] = k , cnt[k] -- ;
                    } else {
                        while( len - tlen ){
                            out[++tlen] = k ; cnt[k] -= 2 ;
                        }
                    }
                }
                for( int k = 1 ; k <= len ; k ++ ) printf( "%c" , out[k] ) ;
                printf( "%c" , j ) ;
                for( int k = len ; k >= 1 ; k -- ) printf( "%c" , out[k] ) ;
                printf( " " ) ;
            }
        }
    }
}

void solve(){
    if( tots == 0 ){
        printf( "1\n" ) ;
        for( int i = 1 ; i <= 127 ; i ++ )
            if( cnt[i] ){
                int tmp = cnt[i] / 2 ;
                for( int j = 1 ; j <= tmp ; j ++ ) printf( "%c" , i ) ;
            }
        for( int i = 127 ; i >= 1 ; i -- )
            if( cnt[i] ){
                int tmp = cnt[i] / 2 ;
                for( int j = 1 ; j <= tmp ; j ++ ) printf( "%c" , i ) ;
            }
        exit( 0 ) ;
    }

    for( ; lef >= 2*tots ; lef -= 2 , tots += 2 )
        if( lef % tots == 0 && ( lef/tots )%2 == 0 ){
            print() ; exit(0) ;
        }

    printf( "%d\n" , N ) ;
    for( int i = 1 ; i <= N ; i ++ )
        printf( "%c " , ss[i] ) ;
}

int main(){
/*
    for( int i = 1 ; i <= 127 ; i ++ )
        printf( "%d %c\n" , i , i ) ; 
*/
    scanf( "%d" , &N ) ;
    scanf( "%s" , ss + 1 ) ;
    for( int i = 1 ; i <= N ; i ++ )
        cnt[ ss[i] ] ++ ;
    for( int i = 48 ; i <= 122 ; i ++ ){
        if( cnt[i]&1 ){
            tots ++ ; iss[i] = 1 ;
        //  printf( "%c is single\n" , i ) ;
        }
    }
    lef = N - tots ;
    solve() ;
}

收获?emm=====,还是可以,至少完成了上午ACM不想做硬是塞给队友一道bfs题,晚上欠的还是要还。。。
然后感觉近几年ACM与OI在题目类型上的区别越来越小了(因为越来越多的出题人来自大学里的ACM队吗?)。
值得一做且ORZ

Bitset works much better than FFT: yjq_naive, yfzcsc, mcfx

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值