Codeforces Round #775 A-D

总体来说,这场比赛题目好,但是因为很多小的优化没学到,所以C寄了一发,最后机房提前二十分钟关门,D算是寄了。

A. Game
题意:给定一个长度为n的01串,如果是连着的1可以直接走,如果是0可以跳过,当然1也可以跳过,跳过的长度即为花费,问从头走到尾如果只跳一次需要多少花费。

思路:注意读题,只能跳一次,所以只要需要跳,必然是一次性跳过所有的0,直接模拟就好了

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t,n,temp,pos1=0,pos2=0;
    for(cin>>t;t;t--)
    {
        cin>>n;
        pos1=0,pos2=0;
        for(int i=1;i<=n;i++)
        {
            cin>>temp;
            if(!temp&&!pos1)
                pos1=i;
            if(!temp)
                pos2=i;
        }
        if(pos2==0)
            cout<<0<<endl;
        else
        cout<<pos2-pos1+2<<endl;
    }
    return 0;
}

B - Game of Ball Passing
题意:n个人互相传球,每个人传球的次数已知,问他们最少用了多少个球。

思路:用最大的传球次数减去所有的,小于等于0就只用了一个球,否则就输出剩下的

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define N 1000000+100
long long a[N];
int main()
{
    int t;
    for(cin>>t;t;t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        if(a[n]==0)
        {
            cout<<0<<endl;
            continue;
        }
        for(int i=n-1;i>=1;i--)
            a[n]-=a[i];
        if(a[n]<=0)
            cout<<1<<endl;
        else
            cout<<a[n]<<endl;
    }
    return 0;
}

C - Weird Sum
题意:给定一个矩阵,每个单元格有一个数字代表颜色,求所有颜色相同的单元格任意组合的曼哈顿距离
思路:暴力,直接写个桶把所有颜色相同的装在一起,再枚举求和的时候注意用多项式的规律优化一下,不然会TLE

#include <bits/stdc++.h>
using namespace std;
#define N 1000000+100
struct node{
    long long x,y,c;
};
node a[N];
long long col[N],sum[N];
bool cmp1(node x,node y){
    return x.c<y.c;
}
bool cmp2(node x,node y){
    return x.x>y.x;
}
bool cmp3(node x,node y){
    return x.y>y.y;
}
int main()
{
   // freopen("in.txt","r",stdin);
    register int n,m,cnt=0,maxx=-1,minn=1e9;
    scanf("%d%d",&n,&m);
    for(register int i=1;i<=n;i++)
    {
        for(register int j=1;j<=m;j++)
        {
            scanf("%d",&a[++cnt].c);
            a[cnt].x=i;
            a[cnt].y=j;
            col[a[cnt].c]++;
            maxx=maxx>a[cnt].c?maxx:a[cnt].c;
            minn=minn<a[cnt].c?minn:a[cnt].c;
        }
    }
    sort(a+1,a+cnt+1,cmp1);
    for(register int i=minn;i<=maxx;i++)
        sum[i]=sum[i-1]+col[i];
    register long long ans=0;
    for(register int i=minn;i<=maxx;i++)
    {
        sort(a+sum[i-1]+1,a+sum[i]+1,cmp2);
        for(register int j=1+sum[i-1],k=sum[i]-sum[i-1]-1;j<=sum[i];k-=2,j++)
            ans+=a[j].x*(long long)k;
        sort(a+sum[i-1]+1,a+sum[i]+1,cmp3);
        for(register int j=1+sum[i-1],k=sum[i]-sum[i-1]-1;j<=sum[i];k-=2,j++)
            ans+=a[j].y*(long long)k;
    }
    cout<<ans<<endl;
    return 0;
}

D - Integral Array
正难则反
题意:给定一个数列,我们要求这个数列选取任意两个满足x<=y的数x,y(x和y可以相同),都满足y/x向下取整存在于数组中。
如果满足要求输出YES
否则输出NO

思路:我们每次分析不满足题意的情况是存在一个r不属于数列并且有y/x=r,所以我们可以枚举所有数组中不存在的数,如果对于这个不存在的数r在数组中有y/x能和r相等,那么就肯定不满足题意了。

#include <stdio.h>
#include <algorithm>
using namespace std;
#define N 1000000+100
 
int a[N];
bool vis[N];
int main()
{
    register int t,n,c;
    //freopen("in.txt","r",stdin);
    for(scanf("%d",&t);t;t--)
    {
        scanf("%d%d",&n,&c);
        for(register int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]]=1;
        }
        sort(a+1,a+n+1);
        bool falg=true;
        for(register int i=1;i<=c;i++)
        {
            if(vis[i])
                continue;
            if(!falg)
                break;
            for(register int j=i;j<=c;j+=i)
            {
                register int y=j/i;
                if(!vis[y])
                    continue;
                register int pos=lower_bound(a+1,a+n+1,j)-a;
                if(pos==n+1||a[pos]>=y+j)
                    continue;
                else
                {
                    falg=false;
                    break;
                }
            }
        }
        if(falg)
            puts("YES");
        else
            puts("NO");
        for(register int i=1;i<=n;i++)
            vis[a[i]]=false;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值