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

A. Permutation Forgery

因为只要排完序一样,所以逆序输出即可。

#include <iostream>
#include <stdio.h>
using namespace std;
int T,n;
int a[105];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
        for(int i=n;i>=1;i--)
        printf("%d ",a[i]);
        puts("");
    }
    return 0;
}

B. Array Cancellation

只有正数在前,负数在后,才可无消耗改变。所以,我们遇到正数,将其加入集合,然后遇到负数,就与之前加入集合的正数消耗。如果正数被消耗完,负数还在,那就加上负数的相反数。最后加上集合中的正数。然后除2即可(因为消耗1可以改变2个)。

#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=1e5+5;
int T,n;
int a[maxn];
int b[maxn];
int cnt;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        long long ans=0;
        cnt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
        for(int i=1;i<=n;++i)
        {
            if(a[i]>0)
            {
                b[++cnt]=a[i];
            }
            else
            if(a[i]<0)
            {
                while(cnt)
                {
                    if(b[cnt]>=-a[i])
                    {
                        b[cnt]+=a[i];
                        a[i]=0;
                        if(!b[cnt])
                        cnt--;
                        break;
                    }
                    else
                    {
                        a[i]+=b[cnt];
                        cnt--;
                    }
                }
                if(a[i]!=0)
                ans-=(long long)a[i];
            }
            //cout<<ans<<endl;
        }
        while(cnt)
        {
            ans+=(long long)b[cnt];
            cnt--;
        }
        printf("%lld\n",ans/2);
    }
    return 0;
}

C. Balanced Bitstring

很好的思维题,我们发现,当向后遍历时,只要前面少的那个与后面多的那个一样,就满足条件。因此,只要a[i]与a[i%k]一样,并且前k个满足条件,之后就一定满足。所以我们保证a[i]与a[i%k]相等,如果a[i]等于?,既可以当1,也可以当0。最后,判断一下前k个是否满足条件即可。

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=3e5+5;
int T,n,k;
char a[maxn];
int b[3];
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        b[0]=b[1]=b[2]=0;
        scanf("%d%d",&n,&k);
        scanf("%s",a);
        int flag=0;
        int t=k>>1;
        for(int i=k;a[i];++i)
        {
            if(a[i]==a[i%k]||a[i]=='?')
            continue;
            if(a[i%k]=='?')
            a[i%k]=a[i];
            else
            {
                flag=1;
                break;
            }
        }
        if(flag)
        {
            puts("NO");
            continue;
        }
        for(int i=0;i<k;++i)
        {
            if(a[i]!='?')
            b[a[i]-'0']++;
        }
        if(b[0]>t||b[1]>t)
        flag=1;
        if(flag)
        puts("NO");
        else
        puts("YES");
    }
    return 0;
}

D. Tree Tag

树上博弈,我们发现,如果 2da>=db,那么就一定可以追到。如果 2da>=树的直径,那么也一定可以追到。如果起初Alice在a点可在da内到达b,那么也可以追到。如果都不满足,Alice必定追不到,因为只要靠近Bob在da内,Bob就可以和他拉开至少da+1,这样便永远追不到。

#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn=1e5+5;
struct node
{
    int to,next;
}edge[maxn<<1];
int head[maxn];
int T,n,a,b,da,db,cnt,dist;
int dp1[maxn],dp2[maxn];
int depth[maxn];
void add(int x,int y)
{
    edge[++cnt].to=y;
    edge[cnt].next=head[x];
    head[x]=cnt;
}
void dfs(int u,int fa)
{
    dp1[u]=dp2[u]=0;
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa)
        continue;
        dfs(v,u);
        if(dp1[u]<dp1[v]+1)
        {
            dp2[u]=dp1[u];
            dp1[u]=dp1[v]+1;
        }
        else
        if(dp1[v]+1>dp2[u])
        {
            dp2[u]=dp1[v]+1;
        }
    }
}
void dis(int u,int fa)
{
    depth[u]=depth[fa]+1;
    if(u==b)
    {
        dist=depth[u]-1;
        return;
    }
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==fa)
        continue;
        dis(v,u);
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        cnt=0;
        scanf("%d%d%d%d%d",&n,&a,&b,&da,&db);
        for(int i=1;i<=n;++i)
        head[i]=0;
        for(int i=1;i<n;++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        if(2*da>=db)
        {
            puts("Alice");
            continue;
        }
        dfs(1,0);
        int ma=0;
        for(int i=1;i<=n;++i)
        ma=max(ma,dp1[i]+dp2[i]);
        if(ma<=2*da)
        {
            puts("Alice");
            continue;
        }
        dis(a,0);
        if(dist<=da)
        {
            puts("Alice");
        }
        else
        {
            puts("Bob");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值