• Codeforces Round #380 (Div. 2) 解题报告


    第一次全程参加的CF比赛(虽然过了D题之后就开始干别的去了),人生第一次codeforces上分……(或许之前的比赛如果都参加全程也不会那么惨吧),终于回到了specialist的行列,感动~。虽然最后也只过了A、B、D3题,但能上分还是非常的激动不已呀。

    先发出来A、B、D的参考解法,C比赛时读了题感觉自己可以做出来,但时间只剩20分钟了,索性弃疗……。

    11.23 补充上了C的参考代码

    A题:

    题目地址

    用一些str函数应该也可以做,但考虑到字符串长度只有不到100以及题目整体不是很复杂,不如直接求解。

    从头开始扫描,寻找为“ogo”的子串(注意扫到倒数第三个数就结束),如果扫到了那么就输出”***“并继续看“go"能重复多少个,这个过程都只用while循环控制一下就可以了。最后再从最后的位置到n用for循环(如果此时已经到头了那么for循环也不会也不需要进行了)

     1 #include<stdio.h>
     2 #include<bits/stdc++.h>
     3 #include <iostream>
     4 using namespace std;
     5 char a[106];
     6 int n,i=0;
     7 bool check()
     8 {
     9     if(a[i]=='o'&&a[i+1]=='g'&&a[i+2]=='o')
    10         return true;
    11     return false;
    12 }
    13 int main()
    14 {
    15 
    16     scanf("%d",&n);
    17     scanf("%s",a);
    18 while(i<=n-3)
    19     {
    20         if(check())
    21             {
    22                 i+=3;
    23             while(a[i]=='g'&&a[i+1]=='o')
    24                 i+=2;
    25             printf("***");
    26             }
    27         else
    28         {
    29             printf("%c",a[i]);
    30             i++;
    31         }
    32     }
    33     for(int j=i;j<n;j++)
    34         printf("%c",a[j]);
    35     return 0;
    36 }

    B题:

    题目地址

    只需要看从每个1能没有阻挡的直走到多少个0,将这些加起来即为所求的答案。所以扫一遍整个图,从每个1出发,向四周走,遇到1或走到边界停下,不然个数就+1。

     1 #include<stdio.h>
     2 #include<bits/stdc++.h>
     3 #include <iostream>
     4 using namespace std;
     5 int n,m,an,ii,jj;
     6 int lo[2000][2000],dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
     7 int main()
     8 {
     9     int i,j,k;
    10     scanf("%d%d",&n,&m);
    11     an=0;
    12     for(int i=1;i<=n;i++)
    13     {
    14         for(int j=1;j<=m;j++)
    15             scanf("%d",&lo[i][j]);
    16     }
    17     for(i=1;i<=n;i++)
    18     {
    19         for(j=1;j<=m;j++)
    20         {
    21             if(lo[i][j]==1)
    22             {
    23                 for(k=0;k<4;k++)
    24                 {
    25                         ii=i;
    26                         jj=j;
    27                     while((ii>0&&ii<=n&&jj>0&&jj<=m&&lo[ii][jj]==0)||(ii==i&&jj==j))
    28                     {
    29                         ii+=dir[k][0];
    30                         jj+=dir[k][1];
    31                         if(ii>0&&ii<=n&&jj>0&&jj<=m&&lo[ii][jj]==0)
    32                             {an+=1;
    33                             }
    34                         else break;
    35                     }
    36                 }
    37             }
    38         }
    39     }
    40     printf("%d
    ",an);
    41     return 0;
    42 }

    C题

    二分查找,先按汽车油箱容量递增排序,二分查找符合条件的油箱最小容量。再排序,找最低的价格。初始设定答案为一个很大的数,如果最后答案不变输出-1,不然输出新的最小价格。

    题目地址

     1 #include<stdio.h>
     2 #include<bits/stdc++.h>
     3 #include <iostream>
     4 using namespace std;
     5 long long int k,n,x=0,dis[200005];
     6 long long int s,t,time1,an,l,r,mid;
     7 bool cmp(long long x,long long y)
     8 {
     9     return x<y;
    10 }
    11 struct oh
    12 {
    13     long long cap,val;
    14 }che[200005];
    15 bool cmp2(oh x,oh y)
    16 {
    17     if(x.cap!=y.cap)
    18         return x.cap<y.cap;
    19     else
    20         return x.val<y.val;
    21 }
    22 bool cmp3(oh x,oh y)
    23 {
    24     return x.val>y.val;
    25 }
    26 int main()
    27 {
    28     scanf("%I64d%I64d%I64d%I64d",&n,&k,&s,&t);
    29     long long int i,j;
    30     dis[0]=0;
    31     an=20000000005;
    32     for(i=1;i<=n;i++)
    33     {
    34         scanf("%I64d%I64d",&che[i].val,&che[i].cap);
    35     }
    36     for(i=1;i<=k;i++)
    37     {
    38         scanf("%I64d",&dis[i]);
    39     }
    40     sort(dis+1,dis+k+1,cmp);
    41     sort(che+1,che+n+1,cmp2);
    42     dis[k+1]=s;
    43     time1=0;
    44     l=1;r=n;
    45     while(l<=r)
    46     {
    47         mid=(l+r)/2;
    48         for(j=1;j<=k+1;j++)
    49         {
    50             if(dis[j]-dis[j-1]>che[mid].cap)
    51                 break;
    52             else
    53             {
    54                 if(x<che[mid].cap-2*(dis[j]-dis[j-1]))
    55                     time1+=(dis[j]-dis[j-1]-x);
    56                 else
    57                     time1+=(3*(dis[j]-dis[j-1])-che[mid].cap);
    58             }
    59         }
    60         if(j==k+2&&time1<=t)
    61         {
    62             r=mid-1;
    63         }
    64         else
    65         {
    66             l=mid+1;
    67         }
    68         time1=0;
    69     }
    70 if(r<n)
    71     {sort(che+r+1,che+n+1,cmp3);
    72     printf("%I64d
    ",che[n].val);}
    73     else
    74         printf("-1
    ");
    75 return 0;
    76 }

    D题

    题目地址

    我的做法貌似有点麻烦。对整个字符串现在前面加上1,末尾加上1,之后扫描一遍,对于连续的0长度小于船长的部分直接填上1。并用he代表余下为0的个数,最少的操作数即为通过最少的操作达到he<船长*船个数的状态。(注意到射击1个1右面数第”船长“个0如果没有打中船,那么从这个1到那个位置之间所有的都一定不会是船的一部分)这样之后从左往右扫,遇到a[i]=1,a[i+1]=0就意味着从第i个数开始一定有不小于船长个连续的0,这样对其操作一定不会产生”浪费“,一定会是最优的操作。如果是1而下个数不是0,那么就是碰上连续1的情况,i++即可,如果是0的话,he--,继续扫描,注意要用一个计数变量记录连续这样的0有多少个,如果达到船长就意味着有必要进行一次操作,以求达到最优的解法。

    #include<stdio.h>
    #include<bits/stdc++.h>
    #include <iostream>
    using namespace std;
    char a[200030];
    int n,ge,len,st,en,i,j,he=0,k,cnt=0,an[200030],s,geshu,chang;
    int main()
    {
        scanf("%d%d%d%d",&n,&ge,&len,&k);
        a[0]='1';
        scanf("%s",a+1);
        a[n+1]='1';
        st=0;en=0;
    he=n-k;
        for(i=1;i<=n+1;i++)
        {
            if(a[i]=='1')
            {
                en=i;
                if(en-st-1>0&&en-st-1<len)
                    {for(i=st+1;i<en;i++)
                        a[i]='1';
                    he-=(en-st-1);
                    }
                else
                    if((en-st-1)%len!=0)
                {
                    for(j=en-1;j>=en-(en-st-1)%len;j--)
                        {a[j]='1';
                        he--;
                        }
                }
                    st=i;
            }
        }
        chang=len*ge;
        i=0;
        while(he>=chang)
        {
            if(a[i]=='1'&&a[i+1]=='0')
            {
                geshu=0;
                an[cnt]=i+len;
                cnt++;
                for(j=i+1;j<=i+len;j++)
                {
                    a[j]='1';
                }
                he-=len;
                i=i+len;
            }
            else{
        if(a[i]=='1')
            {
                geshu=0;
                while(a[i]!='0')
                    i++;
                i--;
            }
        else
        {
            if(geshu<len-1)
            {
                a[i]='1';
                geshu++;
                he--;
            }
            else
            {
                he--;
                geshu=0;
                a[i]='1';
                an[cnt]=i;
                cnt++;
            }
        }
            }
        }
        printf("%d
    ",cnt);
        for(i=0;i<cnt;i++)
            printf("%d ",an[i]);
            return 0;
    }

    通过这次CF,发现或许自己没有自己之前想象的那么水,以后再参加比赛一定好好对待,全程参加,不再划水了。

  • 相关阅读:
    SpringBoot 应用程序启动过程探秘
    git创建分支并推送远程
    idea中@Autowired注解下变量报红
    java.lang.IllegalStateException: Either 'name' or 'value' must be provided in @FeignClient的解决方案
    项目启动中报错Address already in use: bind的解决方案
    Maven配置阿里云镜像和配置jdk1.8编译项目
    MySQL优化之Explain
    英文字母和中文汉字在不同字符集编码下的字节数
    Netty中两种Keepalive的区别
    @ConfigurationProperties和@Value的区别
  • 原文地址:https://www.cnblogs.com/quintessence/p/6083601.html
Copyright © 2020-2023  润新知