Codeforces Round #668 (Div. 2)(A B C D)

题目列表


A - Permutation Forgery

思路:直接倒序输出即可。
代码:

int sum[105];
int a[105];
int b[105];
int n;
int main()
{
    int TT;
    cin>>TT;
    while(TT--){
        scanf("%d",&n);
        int num;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=n;i>=1;i--){
            printf("%d ",a[i]);
        }
        cout<<endl;
    }
    return 0;
}


B - Array Cancellation

思路:从1开始求和,求前i项和最小的数即可,最后输出这个数的绝对值。
代码:

ll a[100005];
int n;
int main()
{
    int TT;
    cin>>TT;
    while(TT--){
        scanf("%d",&n);
        ll minn=0;
        ll num=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            num+=a[i];
            minn=min(num,minn);
        }
        printf("%lld\n",abs(minn));
    }
    return 0;
}


C - Balanced Bitstring

题意:有一个由01组成的字符串,其中有一些是?,问你是否有可能让这个串中所有长度为k的子串的01数量相等。
思路:由于是所有子串,很显然: s[i]=s[i+k]=s[i-k]
在这个条件下,可以把一些?的值确定下来,如果有s[i]!=s[i+k]或s[i]!=s[i-k],则直接输出no 。最后只需要判断s[1]~s[k]这个子串是否可以符合01数量相等即可。
代码:

char s[300005];
int n,k;
int main()
{
    int TT;
    cin>>TT;
    while(TT--){
        scanf("%d %d",&n,&k);
        getchar();
        for(int i=1;i<=n;i++){
            scanf("%c",&s[i]);
        }
        int kk=1;
        for(int i=1;i<=n-k;i++){
            if(s[i]!=s[i+k]&&s[i]!='?'&&s[i+k]!='?'){
                kk=0;
                break;
            }
            if(s[i]!=s[i+k]){
                if(s[i]=='?'){
                    s[i]=s[i+k];
                }
                if(s[i+k]=='?'){
                    s[i+k]=s[i];
                }
            }
        }
        if(kk){
            for(int i=n;i>k;i--){
                if(s[i]!=s[i-k]&&s[i]!='?'&&s[i-k]!='?'){
                    kk=0;
                    break;
                }
                if(s[i]!=s[i-k]){
                    if(s[i]=='?'){
                        s[i]=s[i-k];
                    }
                    if(s[i-k]=='?'){
                        s[i-k]=s[i];
                    }
                }
            }
        }
        if(!kk){
            printf("NO\n");
        }else{
            int num=0,pp=0;
            for(int i=1;i<=k;i++){
                if(s[i]=='?'){
                    num++;
                }else if(s[i]=='1'){
                    pp++;
                }
            }
            int qq=k-pp-num;
            if(num-abs(pp-qq)>=0&&(num-abs(pp-qq))%2==0){
                kk=1;
            }else{
                kk=0;
            }
            if(kk){
                printf("YES\n");
            }else{
                printf("NO\n");
            }
        }
    }
    return 0;
}

D - Tree Tag

题意:A和B分别在一棵树的不同节点上,A最多一步移动da个,B最多移动db格,在10^100步的范围内,如果A和B在同一格,则A获胜,否则B获胜。
思路:10^100很大,就是无限步,很显然,B只有在这棵树的最长路径上活动是最优的,也就是在树的直径上。首先,如果A和B两点的初始距离<=da,那么A可以一步抓住B。对于B最优的就是在直径的一端,当A靠近距离小于等于da时,就逃走,那么要逃到A不可以够到的范围,就最少要跳\(2\times da+1\),那么此时就要保证\(db>2\times da\),因为要跳那么多步,就要保证直径大于\(2\times da\)
代码:

const int maxn=100010;
int n,a,b,da,db;
struct node{int v,dis,nxt;}E[maxn<<2];
int head[maxn],tot=0;
int dp[maxn],mxlen;
void init()
{
    tot=0;
    mxlen=0;
    mem(head,0);
}
void add(int u,int v,int dis)
{
    E[++tot].nxt=head[u];
    E[tot].v=v; E[tot].dis=dis;
    head[u]=tot;
}
void DP(int u,int pa)
{
    dp[u]=0;
    for(int i=head[u];i;i=E[i].nxt)
    {
        int v=E[i].v;
        if(v==pa) continue;
        DP(v,u);
        mxlen=max(mxlen,dp[u]+dp[v]+E[i].dis);
        dp[u]=max(dp[u],dp[v]+E[i].dis);
    }
}
int vis[maxn];
struct num{
    int x,dd;
};
int bfs()
{
    queue<num>q;
    num s1;
    s1.x=a;
    s1.dd=0;
    q.push(s1);
    vis[a]=1;
    while(!q.empty()){
        num s2=q.front();
        q.pop();
        int u=s2.x;
        vis[u]=1;
        for(int i=head[u];i;i=E[i].nxt){
            int v=E[i].v;
            num s3;
            s3.x=v;
            s3.dd=s2.dd+1;
            if(v==b){
                return s3.dd;
            }
            if(vis[v]==1)continue;
            q.push(s3);
        }
    }
    return 0;
}
int main()
{
    int TT;
    cin>>TT;
    while(TT--){
        init();
        mem(vis,0);
        scanf("%d %d %d %d %d",&n,&a,&b,&da,&db);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d %d",&u,&v);
            add(u,v,1);
            add(v,u,1);
        }
        DP(1,0);
        int dd=bfs();
        if(dd>da&&2*da+1<=mxlen&&2*da+1<=db){
            printf("Bob\n");
        }else{
            printf("Alice\n");
        }
    }
    return 0;
}

总结

不足之处:对读题没有耐心。
容易紧张,想不到简单思路。
提高字符串方面的思维能力。
在考虑博弈问题时,要思考对某一方的最坏情况。
要提高从复杂的转化为已知或熟悉的能力。

posted @ 2020-09-07 17:30  hachuochuo  阅读(157)  评论(0编辑  收藏  举报