Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round)【A、B、C题】

A. Contest for Robots

签到题,注意特判即可。

#include <bits/stdc++.h>
using namespace std;
const int N=110;
int n,s1,s2,ans,a[N],b[N];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        cin>>b[i];
        if(a[i]==1&&b[i]==0)s1++;
        else if(a[i]==0&&b[i]==1)s2++;
    }
    if(s1==0)printf("-1\n");
    else if(s1>s2)printf("1\n");
    else
    {
        if(s2%s1==0)ans=s2/s1+1;
        else ans=(int)ceil(1.0*s2/s1);
        printf("%d\n",ans);
    }
    return 0;
}

B. Journey Planning

题意是从已知序列中找一个严格递增的子序列,并且这个子序列中任意相邻的两个元素之差等于它们在原序列中的位置之差,求所有满足条件的子序列中元素和的最大值。

条件用公式表示:对于满足要求的子序列中任意两个相邻元素a1,a2(位置分别是pos1,pos2),
都有a1-a2=pos1-pos2(a1<a2,严格递增), 移项得 a1-pos1=a2-pos2。只要满足pos1<pos2,则必有a1<a2,所以只需要遍历一遍原序列,把 a[i]-i 存入一个数组中,所有 a[i]-i 相同的就表示它们能构成一个符合条件的子序列。由于 a[i]-i 可能出现负数,所以可以开个map来当数组,之后遍历找最大值也比较方便。

(我要吐槽一下我自己,这次做了C题,没做B题。之前想复杂了,看到递增序列最大值就往DP方向想了,还想了二分,set,甚至想到树状数组维护元素位置…后来发现移项就行了,我真是QAQ…按codeforces的规律,B题基本上是简单的思维题吧,也别想太复杂了)

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
map<ll,ll>vis;
ll n,mx,a[N];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        vis[a[i]-i]+=a[i];
    }
    for(auto it:vis)
        mx=max(mx,it.second);
    //注意it遍历容器(而不是迭代器),访问容器类型的值是it.second而不是it->second

    //等价于
    /*for(auto it=vis.begin();it!=vis.end();it++)
        mx=max(mx,it->second);*/  //这里是迭代器访问,所以是 -> 符号
    printf("%lld\n",mx);
    return 0;
}

新收获

遍历map有两种方法(可以“偷懒”,以后少写一点)

for(auto it:vis)
cout<<it.second<<endl;//注意it遍历容器(而不是迭代器),访问容器类型的值是it.second而不是it->second
for(auto it=vis.begin();it!=vis.end();it++)
cout<<it->second<<endl;//这里是迭代器访问,所以是 -> 符号

第一种方法用冒号表示遍历vis,但是注意访问map的值是 .(点) 符号,原因是:

1).for循环中val的类型是std::pair.因此,对于map这种关联性容器而言,需要使用val.first或val.second来提取键值。
2).auto自动推导师出的类型是容器中的value_type,而不是迭代器。
(参考文章:C++11 学习笔记 基于范围的for循环

C. Remove Adjacent

题意是给你一个只含小写字母的字符串,每次你可以找一个字符,只要它的相邻字符中存在一个字符比它自己的ascci码小1,那么你就可以删除这个字符,问你最多能删多少个。

由于数据量非常小,只有100,所以直接暴力模拟就行了。稍微加点贪心思想,先删除字典序大的字符,从字母z到字母b的顺序删除(字母a不存在比自己ascci码小1的小写字母)。还有就是注意遍历字符串的时候正反都要遍历一次,防止 bbbba 这种情况误判。

#include <bits/stdc++.h>
using namespace std;
string s;
char ch;
int n,ans,vis[150];
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>ch;
        s+=ch;
        vis[ch]++;
    }
    for(ch='z';ch>='b';ch--)
    {
        if(!vis[ch])continue;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]==ch)
            {
                if((i+1<s.size()&&s[i]-1==s[i+1])||(i-1>=0&&s[i]-1==s[i-1]))
                    s.erase(s.begin()+i),i--,ans++;
            }
        }
        for(int i=s.size()-1;i>=0;i--)//反向遍历,防止bbbba这种情况误判
        {
            if(s[i]==ch)
            {
                if((i+1<s.size()&&s[i]-1==s[i+1])||(i-1>=0&&s[i]-1==s[i-1]))
                    s.erase(s.begin()+i),i++,ans++;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
发布了84 篇原创文章 · 获赞 125 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/ljw_study_in_CSDN/article/details/104604656