zoukankan      html  css  js  c++  java
  • Codeforces Round #634 (Div. 3) A-E2

    地址:http://codeforces.com/contest/1335

        题意:将n分成a,b。保证a>b,问有几种分法

        解析:偶数输出n/2-1,奇数n/2即可

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long ll;    
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            ll n;
            cin>>n;
            if(n%2==0)
                cout<<n/2-1<<endl;
            else
                cout<<n/2<<endl;
        }
    }

         题意:输出一个长为n的字符串,要求a长度里有b个不同字母

         解析:其实弄来弄去还是只看一个len=a的串即可,比如abcabc,a=3, 从i=1到i=3和从i=2到i=4其实是同一个串而已,只是顺序不同罢了。所以根据要求构造成一个len=a,含有b个不同字符的串,然后把这个串依次往后接即可。自己写的有点麻烦......

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set>
    using namespace std;
    typedef long long ll;    
    char ch[2005],s[2005];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n,a,b;
            cin>>n>>a>>b;
            if(a==b)
            {
                int k=0;
                for(int i=0;i<n;i++)
                {
                    char mid=(char)(k+'a');
                    k++;
                    if(k==26)
                        k=0;
                    cout<<mid;
                }
                cout<<endl;
            }
            else
            {
                int k=0;
                int cnt=0;
                int mid;
                char md;
                for(int i=0;i<a;i++)
                {
                    ch[i]=(char)(k+'a');
                    cnt++;
                    if(cnt==b)
                    {
                        mid=i;
                        md=ch[i];
                        break;
                    }                
                    k++;
                }
                for(int i=mid+1;i<a;i++)
                    ch[i]=md;
                int tot=0;
                for(int i=0;i<n;i++)
                {
                    cout<<ch[tot];
                    tot++;
                    if(tot==a-1)
                        tot=0;
                }
                cout<<endl;
            }
        }
    }

         题意:在一个数组中挑些数分成两组,一组各不相等,一组全相等。

         解析:先统计出两个值,cnt:有多少种数。maxx:出现次数最多的数。然后把cnt--,这个cnt就是除了maxx以外有多少种数了。

            然后分情况:1:cnt==maxx,没得说,直接输出cnt

                  2:maxx<cnt。没法进行补救,一组全相等我最大也就分出maxx,没法进行补救措施。这里给出样例:2 2 2 3 3 4 7 8 9供测试证明。

                  3:maxx>cnt。是有可能进行补救的。因为cnt是不包含maxx的,所以可以从maxx挪出来一个放入cnt中,但是要保证两组的元素数目相同,所以要看看maxx-1和cnt+1的大小关系。如果cnt+1>maxx-1了,那肯定是不能往里补的,只能输出cnt。能补的话,就输出cnt+1。给出两个样例:1 2 4 4 4 4 3和2 2 2 2 2  7 4。这俩一个能补一个不能补,可以自行测试一下。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int a[maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            cin>>n;
            map<int,int>mp;
            int maxx=-1,cnt=0;
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
                if(mp[a[i]]==0)
                    cnt++;
                mp[a[i]]++;
                maxx=max(maxx,mp[a[i]]);
            }
            cnt--;
        //    cout<<cnt<<"--"<<maxx<<endl;
            if(maxx==cnt)
            {
                cout<<maxx<<endl;
                continue;
            }        
            else if(maxx<cnt)
            {
                cout<<maxx<<endl;
            }
            else
            {
                if(cnt+1>maxx-1)
                    cout<<cnt<<endl;
                else
                    cout<<cnt+1<<endl;
            }
        }
    }

         题意:给你一个正确的9*9数独矩阵。对它改动不超过9次来实现每行每列每3*3都要有至少两个元素相同。

         解析:这个重在对题意的理解。可以看出,给出的一定是每行每列每3*3都没有重复元素的。所以要让它变成反数独矩阵,只需要任意找一个数x,把所有的x变成y(x!=y)就可以了。这样,保证了每行每列都有重复元素,而对于3*3,已知输入的3*3里一定没有重复元素,那么1-9都出现在了3*3里,我们把x变成y,一定会出现重复。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=10;
    char s[maxn][maxn];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            for(int i=0;i<9;i++)
                cin>>s[i];
            for(int i=0;i<9;i++)
            {
                for(int j=0;j<9;j++)
                {
                    if(s[i][j]=='3')
                        s[i][j]='4';
                }
            }
            for(int i=0;i<9;i++)
                cout<<s[i]<<endl;
        }
    }

         题意:通过任意删除某些元素,来求出最大的aaa....bbb......aaaa(回文)的2x+y来。

         解析:这个题只要把方法想好,直接可以过E2的hard。

           在输入时,用vector来记录每个元素出现的位置。然后来枚举每一个出现次数>1的数,比如当前枚举的数字x的下标为 L1,L2,L3,R1,R2,R3。那么我们需要枚举L3-R1之间的数字,由于a<=26,所以用Num[26]来记录每个数字出现的次数,找出出现次数最多的数字mx,那么答案就更新为max(maxx,mx+2*mid)。这个mid=size/2,size为当前枚举的数字x出现了几次。这个操作,也许会通过一些样例,但还远远不够。

            for(int i=1;i<=26;i++)
            {
                int size=v[i].size(),mid;
                if(size==1)
                    maxx=max(maxx,size);
                if(size<=1)
                    continue;
                mid=size/2;
                int num[30]={0},mx=0;
                for(int j=v[i][mid-1]+1;j<v[i][size-mid];j++)
                {
                    num[a[j]]++;
                }
                for(int j=1;j<=26;j++)
                    mx=max(mx,num[j]);
                maxx=max(maxx,mx+mid*2);
            }

        其实这里也是两个贪心策略,len=2*x+y,x取最大是一个部分,y取最大又是一个部分,要想len最大,两个贪心都要弄一遍,才算完整。   

        给出样例1 2 2 1 2 2 1 2 2 1,根据上一段的做法,得的结果是6,而实际上是要把中间两个1去掉,答案为 1  2 2 2 2 2 2 1,len=8。因为上段的思想是:贪心,两侧数字的数目取最大。取的只是 1  1  2  2   1  1,这个len=6。当以2出现为两边时,中间两个2之间没有元素,为空,所以len=6。所以对于每次枚举的v[x][],还需要以中间向两边扩散,枚举中间空的其他元素出现次数Num[]

         第一次枚举1,1处,然后枚举2,2处.......v[x][]这个x的数目一直在减少,中间的数目一直在增加。注意这里的下标变化:

                for(int j=mid-1;j>0;j--)    //j即为当前一半的长度
                {
                    for(int c=v[i][j-1]+1;c<v[i][j];c++)    //左
                        num[a[c]]++;
                    for(int c=v[i][size-j-1]+1;c<v[i][size-j];c++)//右
                        num[a[c]]++;            
                    for(int c=1;c<=26;c++)
                        mx=max(mx,num[c]);
                    maxx=max(maxx,mx+j*2);    //更新最大值
                }
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn=2e3+10;
    int a[maxn];
    vector<int>v[30];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            for(int i=1;i<=26;i++)    //注意清空
                v[i].clear();
            cin>>n;
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
                v[a[i]].push_back(i);
            }
            int maxx=-1;
            for(int i=1;i<=26;i++)  //枚举位于两侧的数字
            {
                int size=v[i].size(),mid;
                if(size==1)
                    maxx=max(maxx,size);    //单种数字做为答案
                if(size<=1)
                    continue;
                mid=size/2;    //一侧数量
                int num[30]={0},mx=0;
                for(int j=v[i][mid-1]+1;j<v[i][size-mid];j++)
                {
                    num[a[j]]++;
                }
                for(int j=1;j<=26;j++)
                    mx=max(mx,num[j]);
                maxx=max(maxx,mx+mid*2);//两侧取最大的贪心
                for(int j=mid-1;j>0;j--)
                {
                    for(int c=v[i][j-1]+1;c<v[i][j];c++)    //左区间
                        num[a[c]]++;
                    for(int c=v[i][size-j-1]+1;c<v[i][size-j];c++)    //右区间
                        num[a[c]]++;            
                    for(int c=1;c<=26;c++)
                        mx=max(mx,num[c]);
                    maxx=max(maxx,mx+j*2);//中间取最大的贪心
                }
            }
            cout<<maxx<<endl;
        }
    }

        E2:

         题意:E2和E1的不同就是范围了。

         解析:直接用上面那套代码,范围改一下就可以了。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int a[maxn];
    vector<int>v[202];
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int n;
            for(int i=1;i<=200;i++)
                v[i].clear();
            cin>>n;
            for(int i=0;i<n;i++)
            {
                cin>>a[i];
                v[a[i]].push_back(i);
            }
            int maxx=-1;
            for(int i=1;i<=200;i++)
            {
                int size=v[i].size(),mid;
                if(size==1)
                    maxx=max(maxx,size);
                if(size<=1)
                    continue;
                mid=size/2;
                int num[205]={0},mx=0;
                for(int j=v[i][mid-1]+1;j<v[i][size-mid];j++)
                {
                    num[a[j]]++;
                }
                for(int j=1;j<=200;j++)
                    mx=max(mx,num[j]);
                maxx=max(maxx,mx+mid*2);
                for(int j=mid-1;j>0;j--)
                {
                    for(int c=v[i][j-1]+1;c<v[i][j];c++)
                        num[a[c]]++;
                    for(int c=v[i][size-j-1]+1;c<v[i][size-j];c++)
                        num[a[c]]++;            
                    for(int c=1;c<=200;c++)
                        mx=max(mx,num[c]);
                    maxx=max(maxx,mx+j*2);
                }
            }
            cout<<maxx<<endl;
        }
    }
  • 相关阅读:
    三年Android开发经验,挥泪整理字节跳动、微软中国凉经,你不看看吗?
    App怎么做才能永不崩溃
    做了八年的Android开发,谁不是一边崩溃,一边默默坚守!
    阿里员工年年绩效A,晒出收入后感叹:996虽然痛苦,发钱时候真香
    2021阅读书单
    不动产测绘概念
    Elasticsearch 集成
    Elasticsearch 环境
    Elasticsearch 优化
    Elasticsearch入门
  • 原文地址:https://www.cnblogs.com/liyexin/p/12700774.html
Copyright © 2011-2022 走看看