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

来源:互联网 发布:跨运营商之间网络不通 编辑:程序博客网 时间:2024/05/17 04:00

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("");}

原创粉丝点击