zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第三场)题解

    A - Clam and Fish(贪心)

    思路:

    贪心,首先有鱼一定钓鱼,将没有鱼的天数单独拉出来考虑

    首先从无鱼的第一天开始枚举,若当前天数有蛤蜊就收集,若啥都没,则用手头的蛤蜊换鱼

    同时注意当当前手头的蛤蜊数等于剩余的天数,则剩余天数每天都可以换一条鱼

    代码:

    #include<iostream>
    #include<algorithm>
     using namespace std;
     const int maxn=2e6+10;
     char s[maxn];
     int main()
     {
         int t,n;
         scanf("%d",&t);
         while(t--){
             scanf("%d%s",&n,s);;
             int ans=0,num=0,x=0;
             for(int i=0;i<n;i++)
                 if(s[i]=='0'||s[i]=='1') num++;
             for(int i=0;i<n;i++){
                 num-=(s[i]=='0'||s[i]=='1');
                 if(s[i]=='0'){
                     if(x){
                         ans++;
                         x--;
                     }
                 }
                else if(s[i]=='1'){
                    if(x+1>num&&x){
                        x--;
                        ans++;
                    }    
                    else x++;
                } 
                 else ans++;
             }
             cout<<ans<<endl;
         }
        return 0;
     }

    B - Classical String Problem(模拟)

    思路:

    其实操作一只是在改变字符串循环的开头而已,我们只要记录头指针即可

    代码:

    #include"bits/stdc++.h"
    using namespace std;
    char s[2000005];
    int n;
    int q;
    int p;
    int main()
    {
        int T;
        char ss[4];
        scanf("%s",s);
        n=strlen(s);
        cin>>T;
        while(T--)
        {
            scanf("%s",ss);scanf("%d",&p);
            if(ss[0]=='M')
            {
                q+=p;
                q%=n;
                if(q<0)q+=n;
            }
            else
            {
                int t;
                printf("%c
    ",s[(p+q-1)%n]);
            }
        }
        return 0;
    }

    C - Operation Love(几何)

    思路:

    我们找三条比较有特征的边,大拇指外侧,底侧,小指外侧长度分别为$6,9,8$

    用叉积判断点是顺时针还是逆时针给出的,然后看顺时针/逆时针方向上这三条边顺序,即可判断左右手

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    const int maxn=30;
    double a[maxn],b[maxn];
    double d[maxn];
    double jud(int s,int t){
        return sqrt((a[s]-a[t])*(a[s]-a[t])+(b[s]-b[t])*(b[s]-b[t]));
    }
     
    int S(int p1,int p2,int p3){  // 1 right  2 left
        double ans=(a[p1]-a[p3])*(b[p2]-b[p3])-(b[p1]-b[p3])*(a[p2]-a[p3]);
        if(ans>0) return 1;
        else return 0;
    }
    int main(){
        int T;
        cin>>T;
        while(T--){
            for(int i=1;i<=20;i++){
                scanf("%lf%lf",&a[i],&b[i]);   
            }
            int p1,p2,p3;
            int get8=0,get9=0;
            for(int i=1;i<=19;i++){
                d[i]=jud(i,i+1);
            }d[20]=jud(20,1);
            d[21]=d[1]; a[21]=a[1]; b[21]=b[1];a[22]=a[2]; b[22]=b[2];
            for(int i=1;i<=20;i++){
                if(abs(d[i]-9)<=0.01 &&  abs(d[i+1]-8)<=0.01){
                    p1=i;p2=i+1;p3=i+2;
                    if(S(p1,p2,p3)) cout<<"right"<<endl;
                    else cout<<"left"<<endl;
                }
                if(abs(d[i]-8)<=0.01 &&  abs(d[i+1]-9)<=0.01){
                    p3=i;p2=i+1;p1=i+2;
                    if(S(p1,p2,p3)) cout<<"right"<<endl;
                    else cout<<"left"<<endl;
                }
            }
             
        }
    }

    D - Points Construction Problem(构造)

    代码:

    #include"bits/stdc++.h"
    using namespace std;
    int a[60];
    int b[60];
    int dx,dy;
    int px[60],py[60];
    int m[7][7]={1, 2,  9,  10,  25,  26,  49,
                 4, 3,  8,  11,  24,  27,  48,
                 5, 6,  7,  12,  23,  28,  47,
                 16, 15,  14,  13,  22,  29,  46,
                 17, 18,  19,  20,  21,  30,  45,
                 36, 35,  34,  33,  32,  31,  44,
                 37, 38,  39,  40,  41,  42,  43
    };
    void out(int t)
    {
        for(int i=1;i<=t;i++)printf("%d %d
    ",px[i]+dx,py[i]+dy);
        dx+=50;
    }
    void out2(int t,int m)
    {
        if(m==b[t])
        {
            out(t);
            return;
        }
        if(t>=4&&m-2==b[t-1])
        {
            out(t-1);
            printf("%d %d
    ",-1+dx-50,0+dy);
            return;
        }
        for(int i=1;i<=t;i++)
        {
            if(b[t-i]<=m-b[i]&&m-b[i]<=a[t-i])
            {
                out(i);
                out2(t-i,m-b[i]);
                return;
            }
        }
    }
    int main()
    {
        a[1]=b[1]=4;
        for(int i=2;i<55;i++)
        {
            a[i]=a[i-1]+4;
        }
        int k=0,t=0;
        for(int i=2;i<55;i++)
        {
            if(t<k/2)b[i]=b[i-1],t++;
            else
            {
                b[i]=b[i-1]+2;
                k=k+1;
                t=0;
            }//cout<<i<<":"<<b[i]<<endl;//<<"   "<<k<<endl;
        }
        //for(int i=0;i<55;i++)cout<<i<<":"<<b[i]<<endl;
        for(int i=0;i<7;i++)for(int j=0;j<7;j++)
        {
            px[m[i][j]]=i;
            py[m[i][j]]=j;
        }//for(int i=1;i<50;i++)cout<<px[i]<<" "<<py[i]<<endl;
        //for(int i=1;i<51;i++)cout<<i<<":"<<b[i]<<"-"<<a[i]<<endl;
        px[50]=7;py[50]=3;
        //
        //
        //
        //
        //
        //out2(11,16);
        int T;
        cin>>T;
        while(T--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            if(m%2)printf("No
    ");
            else if(b[n]<=m&&m<=a[n])
            {
                printf("Yes
    ");
                out2(n,m);
            }
            else
            {
                printf("No
    ");
            }
        }
        return 0;
    }

    E - Two Matchings(DP)

     代码:

    #include"bits/stdc++.h"
    #define ll long long
    using namespace std;
    int a[200015];
    ll dp[200035];
    int main()
    {
        int T;
        cin>>T;
        while(T--)
        {
            int n;
            scanf("%d",&n);
            for(int i=0;i<n;i++)
                scanf("%d",a+i);
            sort(a,a+n);
            for(int i=7;i<n;i+=2)
            {
                dp[i-4]=max(dp[i-4],dp[i-6]);
                dp[i]=dp[i-4]+a[i-3]-a[i-4];
            }
            ll ans=0;
            for(int i=1;i<n;i+=2)ans=max(ans,dp[i]);
            ans=(ll)2*(a[n-1]-a[0])-2*ans;
            ;
            printf("%lld
    ",ans);
            for(int i=0;i<n+10;i++)dp[i]=0;
        }
        return 0;
    }

    F - Fraction Construction Problem(拓展欧几里得)

    代码:

    #include"bits/stdc++.h"
    #define ll long long
    using namespace std;
    void gcd(int a,int b,int *x,int *y)
    {
        if(b==0)
        {
            *x=1;
            *y=0;
            return;
        }
        //x*a-y*b=1
        int k=a/b;
        int c=a%b;
        //a=k*b+c
        int x0,y0;
        gcd(b,c,&x0,&y0);
        //x=-y0,y=-y0k-x0
        ll xx=-y0,yy=-y0*(ll)k-x0;
        //xx+b;yy+a
        ll kk=y0/b;
        xx=xx+kk*b;
        yy=yy+kk*a;
        if(xx<0)xx=xx+b,yy=yy+a;
        *x=(int)xx;
        *y=(int)yy;
    }
    int isprime(int a)
    {
        int p=min((int)sqrt((double)a)+2,a-1);
        for(int i=2;i<=p;i++)
        {
            if(a%i==0)return i;
        }
        return 0;
    }
    int main()
    {//cout<<37*37-3*444;
        int T;
        cin>>T;
        while(T--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            int p=isprime(b);
            if(p==0)
            {
                if(b==1)printf("-1 -1 -1 -1
    ");
                else
                {
                    if(a%b==0)
                    {
                        printf("%d %d %d %d
    ",a/b+1,1,1,1);
                    }
                    else printf("-1 -1 -1 -1
    ");
                }
            }
            else
            {
                if(a%p==0)
                {
                    printf("%d %d %d %d
    ",a/p+1,b/p,1,b/p);
                }
                //
                else
                {
                    int q=b/p;
                    while(1)
                    {
                        if(q%p==0)q/=p;
                        else break;
                    }
                    p=b/q;
                    if(q==1)
                    {
                        printf("-1 -1 -1 -1
    ");
                        continue;
                    }
                    int x,y;
                    gcd(q,p,&x,&y);
                    printf("%lld %d %lld %d
    ",x*(ll)a,p,y*(ll)a,q);
                }
            }
        }
        return 0;
    }

    G - Operating on a Graph(并查集+启发式合并)

    思路:

    我们用并查集去维护每个点到底属于哪个集合

    但是本题比较棘手的地方在于合并,但是我们可以发现这样的一个规律,对于每个点至多只会进行一次把相邻的点变为与自己同集合的操作

    所有,我们对于每个集合开一个链表用于维护本集合中的边缘点(未进行过操作的点)

    在进行吞并操作的时候,一个集合的边缘点就变成了与其相邻集合的所有边缘点,所以这里会有一个合并所有集合边缘点的操作

    这个合并操作我们使用启发式合并,每次都将小的集合加入大的集合中,能有有效的降低时间复杂度

    代码:

    #include<iostream>
    #include<algorithm>
    #include<vector>
     using namespace std;
     const int maxn=8e5+10;
     vector<int> a[maxn];
     int fa[maxn];
     int find(int x)
     {
         return fa[x]==x?x:fa[x]=find(fa[x]);
     }
     int main()
     {
         int t,n,m,q,x,u,v;
         scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            for(int i=0;i<n;i++){
                fa[i]=i;
                a[i].clear();
            }
            for(int i=1;i<=m;i++){
                scanf("%d%d",&u,&v);
                a[u].push_back(v);
                a[v].push_back(u);
            }
            scanf("%d",&q);
            while(q--){
                scanf("%d",&x);
                if(x!=fa[x]) continue;
                vector<int> tmp;
                for(int i=0;i<a[x].size();i++){
                    int v=a[x][i];
                    int rt=find(v);
                    if(x!=rt){
                        if(tmp.size()<a[rt].size()) swap(a[rt],tmp);
                        for(int j=0;j<a[rt].size();j++)
                            tmp.push_back(a[rt][j]);
                        a[rt].clear();
                        fa[rt]=x;
                    }
                }
                swap(tmp,a[x]);
            }
            for(int i=0;i<n;i++)
                printf("%d ",find(i));
            printf("
    ");
        } 
        return 0;
     }

    L - Problem L is the Only Lovely Problem(模拟)

    思路:

    直接进行比对即可

    代码:

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
     using namespace std;
     typedef long long ll;
     int main()
     {
        string s;
        cin>>s;
        int flag=0;
        string tmp="lovely";
        for(int i=0;i<tmp.size();i++){
            if(tmp[i]==s[i]||(s[i]-'A'+'a')==tmp[i]){
                continue;
             }
            flag=1;
            break;
         }
             
        if(flag) cout<<"ugly";
        else cout<<"lovely";
        return 0;
     }
  • 相关阅读:
    编译安装libusb操作流水账
    SM总线控制器没有驱动 关机后又自动重启
    mtd-utils编译安装过程
    STM32开发/烧录/调试环境搭建 基于:Win10+STM32Cube+openocd+cmsis-dap(dap-link)
    EchoServer和EchoClient模型的改进1之多线程
    CountDownLatch分析
    linux-java环境安装以及ssh
    ServerSocket01
    使用SecureCRT工具部署项目
    javaScript笔记01
  • 原文地址:https://www.cnblogs.com/overrate-wsj/p/13342231.html
Copyright © 2011-2022 走看看