3.30训练

1.

题目:Vicious Keyboard

地址:http://codeforces.com/problemset/problem/801/A

大体题意是求给出的一串字符中VK的最大数量,最多可以改变其中一个字符。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
    string s;
    cin>>s;
    int flag=0;
    int ans=0;
    if(s.length()==2)//长度为2的时候只有KV这种情况为0.其余的三种情况都可以通过改变或者不改变得到数量为1
        {
            if(s!="KV")
            {
                cout<<"1"<<endl;
                return 0;
            }

            else
            {
                cout<<"0"<<endl;
                return 0;
            }

        }
    else if(s.length()==1)//数量为1的情况只有0
    {
        cout<<"0"<<endl;
        return 0;
    }

    else
    {

        int len=s.length();
        for(int i=0;i<len-1;i++)
        {
            if(s[i]=='V'&&s[i+1]=='K')//如果找到VK,直接ans++,别忘了i++
            {
                ans++;
                i++;
            }
            else if(s[i]=='V'&&s[i+1]=='V')//如果找到VV,这时候要判断第二个V后面是否是K,如果是K,那么优先找VK,否则才标记一下说明这个地方可以通过改变得到一个VK
            {
                if(s[i+2]=='K')
                    continue;
                else
                {
                    flag=1;
                    i++;
                }
            }
            else if(s[i]=='K'&&s[i+1]=='K')
            {
                flag=1;
                i++;
            }
            else if(s[i]=='K'&&s[i+1]=='V')//当找到KV时,直接continue,因为KV无论怎么样都不能变成VK
                continue;
        }
        if(flag)//当找到VV,KK时,标记为1,说明可以通过改变得到一个VK
        ans+=1;
    cout<<ans<<endl;
    return 0;
    }

}

 

2. 

 Odd sum

 地址:http://codeforces.com/problemset/problem/797/B

题意就是给出n个数字,求这n个数字最大的奇数和。

思路1:奇数和肯定是偶数和奇数相加,所以首先把所有的正偶数相加,将奇数序列从大到小排序,先加上第一个奇数,这时候的和肯定是一个奇数,只有再加偶数才能保证最后是奇数和,所以剩下的奇数两个为一组,如果相加大于0,那就加到和上,最后输出答案。

思路2:把所有的正数加起来,然后判断是否为奇数,如果是直接输出答案。如果不是,找到绝对值最小的那个奇数,然后用现在的和减去这个奇数的绝对值,最后就是答案。

 AC1:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1e5+5;
int cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    int su[maxn];
    int cnt=0;
    long long ans=0;
    for(int i=0;i<n;i++)
    {
        int a;
        cin>>a;
        if(a%2!=0)
            su[cnt++]=a;
        else if(a>0)
            ans+=a;
    }
    sort(su,su+cnt,cmp);
    ans+=su[0];
    for(int i=1;i<cnt-1;i++)
    {
        if((su[i]+su[i+1])>=0)
        {
            ans+=su[i]+su[i+1];
            i++;
        }
    }
    cout<<ans<<endl;
}

AC2:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1e5+5;
int cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n;
    cin>>n;
    int su[maxn];
    int cnt=0;
    long long ans=0;
    int maxx=-0x7fffffff;
    int minn=0x7fffffff;
    for(int i=0;i<n;i++)
    {
        int a;

        cin>>a;
        if(a>0)
            ans+=a;
        if(a%2!=0)
        {
            if(a>0)
            {
               minn=min(minn,a);
            }
            else if(a<0)
            {
                maxx=max(maxx,a);
            }
        }

    }

    if(ans%2==1)
    {
        cout<<ans<<endl;
        return 0;
    }
    else
    {
       int m=min(abs(maxx),abs(minn));
       ans-=m;
        cout<<ans<<endl;
        return 0;
    }
}

 

 3.

 Japanese Crosswords Strike Back

 地址:https://cn.vjudge.net/problem/1161922/origin 

给出一段二进制数字,有几个1相邻就是几,n代表有几组这样的1相邻,比如说0110111,n就是2,构成的数组就是{2,3}。现在给出两个数,n代表数组里面数的个数,x代表二进制数字的长度。下面n个数代表1的长度。

因为两组1之间用一个0隔开,所以用总长度把所有的1的长度减去,然后与n-1作比较,如果相等,那就YES,否则NO。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
    int n,x;
    cin>>n>>x;
    int cnt=0;
    for(int i=0;i<n;i++)
    {
        int a;
        cin>>a;
        cnt+=a;
    }
    x-=cnt;
    if(n-1==x)
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
    return 0;
}

 4.

Bertown Subway

 地址:https://cn.vjudge.net/problem/1161924/origin

通俗地讲,例如第一个案例,2.1.3 ,第一个站的终点站是2,第二个站的终点站是1,第三个站的终点站是3。这时候1.2成一个环,3自成一个环。可以改变两个站的终点站,使得(a,b)有向的数量最大。还是上面这个例子,经过改变后变成2.3.1,这时候第一个站点的终点站是2,第二个站点的终点站是3,第三个站点的终点站是1,1.2.3这三个站成了一个环,那(a,b)就从原来的三个变成了现在的九个。

思路:求出每个环的大小,把最大的的两个合并,剩下的不变,结果是每个环的平方和,注意要用long long。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1e6+5;
int p[maxn];
int vis[maxn];
int cnt[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>p[i];
    }
    int x,sum;
    for(int i=1;i<=n;i++)
    {
        if(vis[i]) continue;
        x=p[i];
        sum=1;
        vis[i]=1;
        while(!vis[x])
        {
            sum++;
            vis[x]=1;
            x=p[x];
        }
        cnt[i]=sum;
    }
    sort(cnt+1,cnt+1+n);
    long long int ans=0;
    if(n>1)
        ans=(long long)(cnt[n]+cnt[n-1])*(long long )(cnt[n]+cnt[n-1]);//合并两个最大的环
    else
        ans=1;
    for(int i=1;i<=n-2;i++)
    {
        ans+=(long long)(cnt[i])*(long long)(cnt[i]);
    }
    cout<<ans<<endl;
    return 0;
}

 5.

Ancient Cipher

 地址:http://poj.org/problem?id=2159

给出两串字符,问是否可以把其中一个经过相应的编码后得到另一串字符。

思路:字母可以重排,那么次序就不重要了,分别统计两串字符中各个字母的个数,然后进行排序,判断两个数组是否相等,例如数组1有一个J,两个W,数组2有一个I,两个Q,这时候就是相等,虽然字母不同,但是字母的个数相同。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
    int num1[100],num2[100];
    string s1,s2;
    cin>>s1>>s2;
    memset(num1,0,sizeof(num1));
    memset(num2,0,sizeof(num2));
    int len=s1.length();
    for(int i=0;i<len;i++)
    {
        num1[s1[i]-'A']++;
        num2[s2[i]-'A']++;
    }
    sort(num1,num1+26);
    sort(num2,num2+26);
    int flag=0;
    for(int i=0;i<26;i++)
    {
        if(num1[i]!=num2[i])
        {
            flag=1;
            break;
        }
    }
    if(!flag)
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值