• 【周赛题解】三


    A. Playing with Paper

    解法用辗转相除法,一边求出最大公约数,一边求出可分割的正方形的数量。

    #include<stdio.h>
    #include<math.h>
    using namespace std;
    typedef long long ll;
    ll ans=0;
    ll gcd(ll a,ll b)
    {
        if(b==0) return a;
        else
        {
            ans+=a/b;
            return gcd(b,a%b);
        }
    }
    int main()
    {
        ll a,b;
        scanf("%I64d%I64d",&a,&b);
        gcd(a,b);
        printf("%I64d
    ",ans);
        return 0;
    }
    

    B. Error Correct System

    用二维数组标记一下转换表再查找就可以啦

    a[i][j]表示字符i转换为字符j的第一个位置

    如果a[i][j]和a[j][i]都有需要转换的话,就交换这两个位置,否则查找如a[i][j],a[j][k]的形式交换,否则不能交换。

    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    using namespace std;
    int len;
    char s1[200005],s2[200005];
    int a1[26][26];
    int main()
    {
        int i,j,ii;
        memset(a1,-1,sizeof(a1));
        scanf("%d",&len);
        getchar();
        gets(s1);
        gets(s2);
        int k=0;
        for(i=0;i<len;i++)
        {
            if(s1[i]!=s2[i])
            {
                a1[s1[i]-'a'][s2[i]-'a']=i;
                k++;
            }
        }
        int ans1=-1,ans2=-1;
        /*for(i=0;i<len;i++)
        {
            if(a1[i]&&a2[i])
            {
                ans1=a1[i];
                ans2=a2[i];
            }
        }*/
        for(i=0;i<26;i++)
        {
            for(j=i+1;j<26;j++)
            {
                if(a1[i][j]!=-1&&a1[j][i]!=-1)
                {
                    ans1=a1[i][j];ans2=a1[j][i];
                    break;
                }
            }
            if(j<26) break;
        }
        if(ans1!=-1)
        {
            printf("%d
    ",k-2);
            printf("%d %d
    ",ans1+1,ans2+1);
        }
        else
        {
            for(i=0;i<26;i++)
            {
                for(j=0;j<26;j++)
                {
                    if(a1[i][j]!=-1)
                    {
                        for(ii=0;ii<26;ii++)
                        {
                            if(a1[j][ii]!=-1)
                            {
                                ans1=a1[i][j];
                                ans2=a1[j][ii];
                                break;
                            }
                        }
                        if(ii<26) break;
                    }
                }
                if(j<26) break;
            }
            if(ans1!=-1)
            {
                printf("%d
    ",k-1);
                printf("%d %d
    ",ans1+1,ans2+1);
            }
            else
            {
                printf("%d
    ",k);
                printf("-1 -1
    ");
            }
        }
        return 0;
    }
    

      

    C. Glass Carving

    本题要使用特殊的数据结构。

    维护横向和纵向的最大宽度,查询时想乘即可。

    #include<stdio.h>
    #include<math.h>
    #include<set>
    #include<map>
    using namespace std;
    set<int> H,V;
    map<int,int> HH,VV;
    int main()
    {
        int w,h,n,z;
        char c;
        scanf("%d%d%d",&w,&h,&n);
        H.insert(0);
        H.insert(h);
        V.insert(0);
        V.insert(w);
        HH[h]=1;
        VV[w]=1;
        while(n--)
        {
            int w;
            getchar();
            scanf("%c%d",&c,&z);
            if(c=='H')
            {
                H.insert(z);
                {
                    int l,r;
                    set<int>::iterator it;
                    it=H.find(z);
                    it--;
                    l=*it;
                    it++;
                    it++;
                    r=*it;
                    HH[r-l]--;
                    if(HH[r-l]==0)
                    {
                        HH.erase(r-l);
                    }
                    HH[z-l]++;
                    HH[r-z]++;
                    printf("%I64d
    ",(long long)(HH.rbegin()->first) *(VV.rbegin()->first) );
                }
            }
            else
            {
                V.insert(z);
                {
                    int l,r;
                    set<int>::iterator it;
                    it=V.find(z);
                    it--;
                    l=*it;
                    it++;
                    it++;
                    r=*it;
                    VV[r-l]--;
                    if(VV[r-l]==0)
                    {
                        VV.erase(r-l);
                    }
                    VV[z-l]++;
                    VV[r-z]++;
                    printf("%I64d
    ",(long long)(HH.rbegin()->first) *(VV.rbegin()->first) );
                }
            }
        }
        return 0;
    }
    

      

    D. Clique Problem

    将问题转换,每个点的x和w值可以转换成区间(x-w,x+w),然后求出不想交的区间的最大个数即答案。

    求法是贪心,每次都选择右边界最小且和之前的区间不想交的区间即可。

    #include<stdio.h>
    #include<math.h>
    #include<map>
    #include<algorithm>
    using namespace std;
    typedef pair<int,int> P;
    P p[200005];
    int main()
    {
        int len,i,x,w;
        scanf("%d",&len);
        for(i=0;i<len;i++)
        {
            scanf("%d%d",&x,&w);
            p[i].first=x+w;
            p[i].second=x-w;
        }
        int to=-1000000005,ans=0;
        sort(p,p+len);
        for(i=0;i<len;i++)
        {
            if(p[i].second>=to)
            {
                ans++;
                to=p[i].first;
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

      

    E. Data Center Drama

    图论题。没A。。

    先判断图是否存在欧拉回路,若不存在则补充边,(度为奇数个的点要补充)。

    求出图的欧拉回路,然后顺着路径翻转编号为奇数(或偶数)的边,最后如果总边数是奇数个,就在出发点加一个自环。

  • 相关阅读:
    Atitit 图像金字塔原理与概率 attilax的理解总结qb23
    Atiti  attilax主要成果与解决方案与案例rsm版 v4
    Atitit 常用比较复杂的图像滤镜 attilax大总结
    Atitit. Api 设计 原则 ---归一化
    Atitit 面向对象弊端与问题 坏处 缺点
    Atitit  记录方法调用参数上下文arguments
    Atitit 作用域的理解attilax总结
    Atitit usrQBM1603短信验证码规范
    atitit 短信验证码的源码实现  .docx
    Atitit 图片 验证码生成attilax总结
  • 原文地址:https://www.cnblogs.com/syiml/p/4364056.html
Copyright © 2020-2023  润新知