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

A Boboniu Likes to Color Balls


分情况讨论一下即可。全为偶数,或者三个为偶数,是肯定可以的。只有两个为偶数是肯定不可以的。有一个为偶数,或者没有一个是偶数的情况,得看是否红,蓝,绿气球都有,如果都有则可以(可以转化成成立的情况),否则不可以。

#include 
#include 
using namespace std;
int T,r,g,b,w;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&r,&g,&b,&w);
        if(r%2==0&&g%2==0&&b%2==0&&w%2==0)
        {
            puts("Yes");
            continue;
        }
        int res=0;
        if(r%2==1)
        res++;
        if(g%2==1)
        res++;
        if(b%2==1)
        res++;
        if(w%2==1)
        res++;
        if(((res==3||res==4)&&r&&g&&b)||(!res)||(res==1))
        {
            puts("Yes");
            continue;
        }
        else
        {
            puts("No");
            continue;
        }
    }
    return 0;
}

B Boboniu Plays Chess


直接按规则,先跑行,再跳到其它列再跑,或者先跑列,再跳到其他行再跑,皆可以。

#include 
#include 
#include 
#include 
using namespace std;
int n,m,Sx,Sy;
int main()
{
    scanf("%d%d%d%d",&n,&m,&Sx,&Sy);
    printf("%d %d\n",Sx,Sy);
    for(int i=m;i>=1;i--)
    {
        if(i!=Sy)
        printf("%d %d\n",Sx,i);
    }
    int flag=1;
    for(int i=1;i<=n;++i)
    {
        if(i!=Sx)
        {
            if(flag)
            {
                for(int j=1;j<=m;++j)
                printf("%d %d\n",i,j);
            }
            else
            {
                for(int j=m;j>=1;j--)
                printf("%d %d\n",i,j);
            }
            flag^=1;
        }
    }
    return 0;
}

C Boboniu and Bit Operations


并不是直接取与的最小值或上就可以,因为如果对于任意的j,ai&bj在某一位上都是1,说明这位必是1,那么再选最小值的不用考虑这一位。所以,我们枚举9位,如果存在1个i对于任意的j,ai&bj在那位都是1,那么那位必取1,否则取0,然后将取1的标记掉,下次不再找它。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn=210;
const int inf=0x3f3f3f3f;
int n,m,ans;
int a[maxn],b[maxn],num[25];
int c[maxn][maxn][10];
int limit[maxn];
bool vis[maxn][maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    scanf("%d",&a[i]);
    for(int j=1;j<=m;++j)
    scanf("%d",&b[j]);
    num[0]=1;
    for(int i=1;i<=9;++i)
    num[i]=num[i-1]*2;
    for(int i=1;i<=n;++i)
    {
        limit[i]=m;
        for(int j=1;j<=m;++j)
        {
        int tmp=a[i]&b[j];
        int tot=0;
        while(tmp)
        {
            c[i][j][tot++]=tmp%2;
            tmp>>=1;
        }
        }
    }
    for(int k=8;k>=0;k--)
    {
        bool flag=0;
        for(int i=1;i<=n;++i)
        {
            int len=0;
            for(int j=1;j<=m;++j)
            {
                if(c[i][j][k]&&!vis[i][j])
                len++;
            }
            if(len==limit[i])
            {
                flag=1;
                ans+=num[k];
                break;
            }
        }
        if(!flag)
        {
            for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            if(c[i][j][k]&&!vis[i][j])
            {
                vis[i][j]=1;
                limit[i]--;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}

D Boboniu Chats with Du


将a[]分成,>m和<=m的两部分,然后>m从大到小排序,<=m从小到大排序,分别求前缀和,然后枚举选>m的数量,利用前缀和,O(1)算出此时最大值更新答案。(注意会爆int)

#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,d,m,x;
int a[maxn],b[maxn];
ll sum1[maxn],sum2[maxn];
int tot1,tot2;
int main()
{
    scanf("%d%d%d",&n,&d,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&x);
        if(x<=m)
        a[++tot1]=x;
        else
        b[++tot2]=x;
    }
    sort(a+1,a+1+tot1);
    sort(b+1,b+1+tot2,greater<int>());
    for(int i=1;i<=tot1;++i)
    sum1[i]=sum1[i-1]+a[i];
    for(int j=1;j<=tot2;++j)
    sum2[j]=sum2[j-1]+b[j];
    if(!tot2)
    {
        printf("%lld\n",sum1[tot1]-sum1[0]);
        return 0;
    }
    ll ans=0;
    for(int i=1;i<=tot2;++i)
    {
        if(i+1ll*i*d<1ll*tot2)
        continue;
        if(i+1ll*(i-1)*d>1ll*n)
        continue;
        ans=max(ans,sum2[i]-sum2[0]+sum1[tot1]-sum1[min(1ll*tot1,max(0ll,1ll*(i-1)*d-(tot2-i)))]);
    }
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(Codeforces排位日记,算法)