• 2018 ACM-ICPC亚洲区域赛(青岛)


    Problem C---zoj 4060 Flippy Sequence

    解题思路:要求进行两次操作,每次操作选择一个区间,问将s串变成t串中所选的两个区间构成的4元组有多少个。做法:找出s串与t串不同块的个数,然后做个简单的判断即可。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=1e6+5;
     5 int T,n,cnt,answer;char s1[maxn],s2[maxn];
     6 int main(){
     7     while(~scanf("%d",&T)){
     8         while(T--){
     9             scanf("%d %s %s",&n,s1,s2);cnt=0;
    10             for(int i=0;i<n;++i)//统计s串与t串不同块的个数
    11                 if((i==0&&s1[i]!=s2[i])||(i>0&&s1[i-1]==s2[i-1]&&s1[i]!=s2[i]))cnt++;
    12             if(!cnt)answer=n*(n+1)/2;//全部相同:1+...+n
    13             else if(cnt==1)answer=2*(n-1);//只有一个不同块,①不同和不同进行反转,②不同和相同进行反转
    14             else if(cnt==2)answer=6;//有两个不同块,三种操作,答案肯定为6
    15             else answer=0;//至少有3个不同块,无法实现2次操作,答案只能为0
    16             printf("%d
    ",answer);
    17         }
    18     }
    19     return 0;
    20 }

    Problem E---zoj 4062 Plants vs. Zombies

    (补)解题思路:典型的最大化最小值,二分解法再加个贪心,详解看代码。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=1e5+5;
     5 int T,n;LL m,l,r,mid,a[maxn],d[maxn];
     6 bool check(LL x){
     7     ///二分总防御值,对于固定的防御值x,显然花园里的每个植物都要不小于x,因此贪心地从左往右寻找每一个防御值小于x的植物,对它和它右侧的植物反复浇水。
     8     LL step=0;
     9     for(int i=0;i<n;++i)d[i]=x/a[i]+(x%a[i]?1LL:0LL);///计算每个至少需要浇水的次数
    10     for(int i=0;i<n;++i){
    11         if(!d[i]){
    12             if(i!=n-1)step++;///如果最后一棵植物需要浇水的次数为0,说明其防御值不小于当前x,则无需计数
    13         }else{
    14             step+=d[i]*2LL-1LL;///累加从i-1走到i这1步+浇完第i棵植物后花费的总步数为2*d[i]-1
    15             d[i+1]-=(d[i]-1LL);///第i+1棵植物需要浇水的次数要减去(d[i]-1)
    16             if(d[i+1]<0)d[i+1]=0LL;///如果d[i+1]<0,说明下一棵植物的防御值早已大于x,下次只需给它浇一次水(贪心向右移动一步)即可
    17         }
    18         if(step>m)return false;///如果所走步数超过m,则直接返回0,找较小的答案x
    19     }
    20     return true;
    21 }
    22 int main(){
    23     while(~scanf("%d",&T)){
    24         while(T--){
    25             scanf("%d%lld",&n,&m);
    26             for(int i=0;i<n;++i)scanf("%lld",&a[i]);
    27             l=1LL,r=1e18;
    28             while(l<=r){///[l,r],退出条件是l>r,即l-1==r
    29                 mid=(l+r)>>1;
    30                 if(check(mid))l=mid+1LL;///还有满足条件的最小值,继续最大化
    31                 else r=mid-1LL;///不满足条件,往左找
    32                 ///cout<<l<<' '<<r<<endl;
    33             }
    34             printf("%lld
    ",l-1);///l-1相当于r,因为l会不断被最大化,直到超过r,则可以取l-1或者r就是最大化最小值答案
    35         }
    36     }
    37     return 0;
    38 }

    Problem J---zoj 4067 Books

    解题思路:没有理解好题意,因此赛场上丧心病狂调了2小时的bug,罚时巨多QWQ,其实就是个简单的贪心=_=。题意:DreamGrid带的钱会在1~n本书中从前往后进行挑选,如果当前剩余的钱不小于第i本书的价格,那么他就一定会买这本书,并且用剩余的钱减去第i本书的价格,直到买完m本书,否则就跳过不买第i本书籍。首先要明确的一点:从其往后有序挑选!!!分三种情况:①当m==n时,显然为"Richman";②当m<cnt_0时,此时可以买比m多的书籍,显然为"Impossible";③当m>cnt_0时,首先肯定会挑选cnt_0个价格为0的书籍,然后从前往后在价格不为0的书籍里面贪心挑选(m-cnt_0)本书籍,再加上后面不为0的最小价格-1即为DreamGrid可带的最多零钱。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;LL ans;//注意用long long
     4 const int inf=0x3f3f3f3f;
     5 const int maxn=1e5+5;
     6 int T,n,m,cnt_0,pos,mina,s[maxn];
     7 int main(){
     8     while(cin>>T){
     9         while(T--){
    10             cin>>n>>m;cnt_0=0;
    11             for(int i=0;i<n;++i)cin>>s[i],cnt_0+=s[i]?0:1;//统计0的个数
    12             if(m==n)puts("Richman");
    13             else if(cnt_0>m)puts("Impossible");//如果0的个数大于m,肯定可以买更多的书籍,显然此时为不可能
    14             else{
    15                 m-=cnt_0,mina=inf,pos=0,ans=0;//m为剩下要挑选的本数
    16                 while(m)s[pos]?ans+=s[pos++],m--:pos++;//贪心选择价格不为0的m本,然后在后面选择一本最小的价格(不为0)-1加上来即为最优答案
    17                 for(int i=pos;i<n;++i)//从连续选择pos个不为0的数后,再从后面选择不为0的最小价格
    18                     if(s[i])mina=min(mina,s[i]);
    19                 cout<<(ans+=mina-1)<<endl;
    20             }
    21         }
    22     }
    23     return 0;
    24 }

    Problem M---zoj 4070 Function and Function

    解题思路:签道题,注意:输入的x为0时要单独考虑。

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 int T,x,k,s[]={1,0,0,0,1,0,1,0,2,1};
     5 int g(int y){
     6     int ans=0;
     7     while(y){ans+=s[y%10];y/=10;}
     8     return ans;
     9 }
    10 int main(){
    11     while(~scanf("%d",&T)){
    12         while(T--){
    13             scanf("%d%d",&x,&k);
    14             if(!x)x=k&1?1:0;//x为0要单独考虑
    15             else{
    16                 for(int i=1;i<=k&&x;++i){
    17                     x=g(x);
    18                     if(!x){x=(k-i)&1?1:0;break;}
    19                 }
    20             }
    21             printf("%d
    ",x);
    22         }
    23     }
    24     return 0;
    25 }
  • 相关阅读:
    求n(n>=2)以内的质数/判断一个数是否质数——方法+细节优化
    poj1185炮兵阵地 正确代码及错误代码分析
    运算符优先级的几点注意
    mod(%)之规律(除数与被除数的正负分析)
    css背景
    Content-Type
    vue数组的增改和v-model的绑定使用Demo
    python open函数关于w+ r+ 读写操作的理解(转)
    http状态码解释
    cookie与token对比(转)
  • 原文地址:https://www.cnblogs.com/acgoto/p/9916105.html
Copyright © 2020-2023  润新知