Codeforces AIM Tech Round 3 (Div. 2)(A-D 未完)

A. Juicer

题意:现在给你n个数,如果大于b,那就扔掉,否则加进去,如果加进去的和大于d,就清空一次,问清空次数
思路:简单模拟

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long m,k;
int main(){
    scanf("%d%I64d%I64d",&n,&m,&k);
    int times=0;
    long long now=0;
    for(int i=0;i<n;i++)
    {
        long long temp;
        scanf("%I64d",&temp);
        if(temp>m) continue;
        now+=temp;
        if(now>k)
        {
            times++;
            now=0;
        }
    }
    printf("%d\n",times);
}

B. Checkpoints

题意:现在在一个直线上有n个点,你初始在一个点,现在你要跑过n-1个点,问最短跑多少
思路:统计好一开始在你位置上的点,在你左边的点,在你右边的点,排序,然后枚举跑左边点的数量,得出右边点的数量,不断更新最小值就好了,不过记得要特判下,一开始就跑好了,全跑左边和全跑右边的情况

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long a[100100];
long long b[100100];
long long init;
int main(){
    scanf("%d%I64d",&n,&init);
    int times=0;
    int l=0;
    int r=0;
    for(int i=0;i<n;i++)
    {
        long long temp;
        scanf("%I64d",&temp);
        if(temp==init)
            times++;
        else if(temp<init)
        {
            a[l++]=temp;
        }
        else
            b[r++]=temp;
    }
    sort(a,a+l);
    sort(b,b+r);
    long long minn=1e18;
    if(times>=n-1)
    {
        printf("0\n");
        return 0;
    }
    for(int i=0;i<=l;i++)
    {
        if(i==0&&r+times>=n-1)
        {
            long long now=abs(init-b[n-times-2]);
            minn=min(minn,now);
        }
        else if(i>=n-1)
        {
            long long now=abs(init-a[l-i]);
            minn=min(minn,now);
        }
        else if(n-1-(i+times)<=r){
            long long now=abs(init-a[l-i]);
            long long now2=abs(init-b[n-times-i-2]);
            now=min(now*2+now2,now+now2*2);
            minn=min(minn,now);
        }
    }
    printf("%I64d\n",minn);
}

C. Letters Cyclic Shift

题意:现在给你一个字符串,要把它的一个子串改变下,按照a->z,b->a,c->b。。。。的规律,问改变一次后所得字符串最小是多少
思路:优先改变前面的,改变到遇到a就停下,注意,必须要改变子串,所以还是要特判下全是a的字符串的情况

代码:

#include<bits/stdc++.h>
using namespace std;
char a[100100];
int main(){
    scanf("%s",a);
    int x=strlen(a);
    bool judge=false;
    for(int i=0;i<x;i++)
    {
        if(i==x-1&&!judge)
        {
            a[i]=(a[i]-'a'+25)%26+'a';
            break;
        }
        else if(a[i]!='a')
        {
            judge=true;
            a[i]--;
        }
        else if(judge&&a[i]=='a')
            break;
    }
    puts(a);
}

D. Recover the String

题意:给你四个数字,分别代表原字符串(原字符串只有’0’,’1’)的”00”,”01”,”10”,”11”这些子串的个数,分别是a1,a2,a3,a4,问存不存在原字符串,有的话输出原字符串,否则输出”Impossible”

思路:根据给的a1和a4,能够推算出原字符串的0,1的个数。
而对于字符串中任意一个’1’,它的后面每个’0’都会让a3加一,它前面每个’1’都会让a2数加一,对于每个’0’也是同理的,这样的东西出现了a3次(对于每个0也是同理的)。那么我就能推导出一个结论,如果有符合条件的字符串,那么必定有:0的个数*1的个数=a2*a3。
然后,从左向右来看,对于一个位置,它选1还是0,只是和剩下的0,1的个数有关,且对于后面的1,0的选择不产生影响,那么我就可以在这个地方选一个0,然后让0的个数减一,同时让a2减去目前1的剩余个数,直到a2小于了剩余1的个数,然后开始选1,不断重复上面的过程,直到1和0的剩余个数都是0为止。

但是,对于a1或者a4等于0的时候,我们需要考虑一个问题,那就是他们也是有可能没有,但是可能是有一个的,这个时候就需要特判了(必须吐槽下,这场BCD都是各种特判,wa到难受),如果中间两个数都是0,那么a1为0时,0个数就是0,a4同理,但是当a1,a4都是0的时候,就需要对a2,a3进行特判了,具体特判结果参考代码

到这里,这个题目的思路就算结束了,但是呢,我们可能会对我们的策略产生怀疑,为什么这样一个类似贪心的做法是正确的。首先,我们的a2,a3都会判断是否能产生一个符合题意得字符串,然后才会开始我们的贪心,而对于a2来说,a2必定大于等于0且小于等于1的个数*0的个数的,那么我们就能保证一定存在一种0的个数的加法使得其和为a2

代码:

#include<bits/stdc++.h>
using namespace std;
long long a[100100];
int main(){
    a[0]=0;
    int n;
    for(n=1;;n++)
    {
        if(a[n-1]>1000000000)
            break;
        a[n]=a[n-1]+n;
    }
    long long q,w,e,r;
    scanf("%I64d%I64d%I64d%I64d",&q,&w,&e,&r);
    bool judge=false;
    int num0=lower_bound(a,a+n,q)-a;
    int num1=lower_bound(a,a+n,r)-a;
    if(q!=a[num0]||r!=a[num1])
        judge=true;
    if(num0==0&&num1==0)
    {
        if(w==1&&e==0)
            printf("01\n");
        else if(w==0&&e==0)
            printf("0\n");
        else if(w==0&&e==1)
            printf("10\n");
        else
            printf("Impossible\n");
        return 0;
    }
    num1++;
    num0++;
    if(num0==1&&w==0&&e==0)
        num0=0;
    if(num1==1&&w==0&&e==0)
        num1=0;

    if(num0*num1!=w+e||judge)
    {
        printf("Impossible\n");
        return 0;
    }
    else
    {
        while(num0!=0||num1!=0)
        {
            if(w>=num1)
            {
                printf("0");
                num0--;
                w-=num1;
            }
            else
            {
                printf("1");
                num1--;
                e-=num0;
            }
        }
    }
    puts("");
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值