Codeforces Round #575 (Div. 3)部分题解(A ~ D2)

39 篇文章 1 订阅

前言

博主也算是毒奶界的一柄利剑。
博主喜欢RNG,RNG无了;
博主喜欢FPX,FPX寄了;
博主之前爱看我英(**东西),结果作者背刺我。

博主在这里毒奶一下,EDG打DK的时候,EDG全员就跟博主刷混沌传送杖的样子一样:刷了2小时毛都没看到,根本看不到胜利的曙光。

在这里插入图片描述

国电要是夺冠,第二天速更最后一篇最小生成树算法讲解,并且之后的Atcoder的每一场ABC必出题解。

不破不立,EDG给我冲!


A - Three Piles of Candies(水题)

比赛链接:https://codeforces.com/contest/1196/problem/A

题目大意

现在这里有三堆糖果,第一堆糖果有 a a a个,第二堆有 b b b个,第三堆有 c c c个。
我们想把这三堆糖果平分给两个人,使得两个人最后得到的糖果数量都是 x x x个。

求出 x x x的最大值。

思路

啊?这种题你都要看题解的?
建议原地给自个埋了吧。

在这里插入图片描述

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--){
        ll a,b,c;
        cin>>a>>b>>c;
        cout<<(a+b+c)/2<<endl;
    }
}

B - Odd Sum Segments (思维+数学)

比赛链接:https://codeforces.com/contest/1196/problem/B

题目大意

给出长度为n的数组a,问是否可以把数组a分割为k个子数组,使得所有子数组的和都是奇数。
如果可以实现,则输出“YES”,并输出一种可行方案;
否则输出“NO”。

例如,样例1中7 18 3 14 1可以分割为718 314 1,所以输出的是1 3 5,分别代表着7、3、1在数组中的下标,意味着把区间 [ 1 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] [1 , 1],[2 , 3],[4 , 5] [1,1][2,3][4,5]各分一组。

思路

这又涉及到了小学数学的知识,详细请见博主在Codeforces Round #753 (Div. 3)部分题解(A ~ E题)中B题的解释。

我们记录下数组中所有奇数的位置。

  • 如果奇数的个数少于k个,那么我们就无法实现题目中的要求(影响每个数组和的奇偶性的因素不在于偶数的个数,而是在于奇数的个数)。

  • 如果奇数的个数大于 k k k个,我们可以让前( k − 1 k-1 k1)个数组每个数组都拿走一个奇数,偶数随便拿,这就能保证前 k − 1 k-1 k1个数组的和一定是奇数。 然后我们把剩下的奇数都分给最后一个数组,这个时候最后一个数组中奇数的个数就决定了这道题的答案。

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

ll a[maxn];

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        vector<int> ans;
        cin>>n>>k;
        for(int i=1; i<=n; i++){
            cin>>a[i];
            if(a[i]&1) ans.push_back(i);
        }
        if(ans.size()<k||(ans.size()-k+1)%2==0) cout<<"NO"<<endl;
        else{
            cout<<"YES"<<endl;
            for(int i=0;i<k-1;i++)
                cout<<ans[i]<<" ";
            cout<<n<<endl;
        }
    }
}

C - Robot Breakout(思维)

比赛链接:https://codeforces.com/contest/1196/problem/C

题目大意

从实验室中跑出了一群暴走的机器人,它们还处于试验阶段,十分的危险。
现在你运用自己的智慧暂时性把所有的机器人都控制了起来,但是它们散落在各处,收集起来十分麻烦,于是你想给所有机器人发送一个坐标,使得所有的机器人都能到达那个坐标,以便于实验室的回收。

由于机器人还处于实验阶段,致使有些机器人还没有被完善。
机器人 i i i有6个属性: X i X_i Xi Y i Y_i Yi f i , 1 f_{i,1} fi,1 f i , 2 f_{i,2} fi,2 f i , 3 f_{i,3} fi,3 f i , 4 f_{i,4} fi,4

  • X i X_i Xi Y i Y_i Yi代表着机器人 i i i现在处于( X i X_i Xi Y i Y_i Yi)的位置;
  • f i , 1 = 0 f_{i,1}=0 fi,1=0,则代表机器人 i i i无法进行( X i X_i Xi Y i Y_i Yi) → ( X i − 1 X_i-1 Xi1 Y i Y_i Yi)的行动;若 f i , 1 = 1 f_{i,1}=1 fi,1=1,则代表机器人 i i i可以进行( X i X_i Xi Y i Y_i Yi) → ( X i − 1 X_i-1 Xi1 Y i Y_i Yi)的行动。
  • f i , 2 = 0 f_{i,2}=0 fi,2=0,则代表机器人 i i i无法进行( X i X_i Xi Y i Y_i Yi) → ( X i X_i Xi Y i + 1 Y_i+1 Yi+1)的行动;若 f i , 2 = 1 f_{i,2}=1 fi,2=1,则代表机器人 i i i可以进行( X i X_i Xi Y i Y_i Yi) → ( X i X_i Xi Y i + 1 Y_i+1 Yi+1)的行动。
  • f i , 3 = 0 f_{i,3}=0 fi,3=0,则代表机器人 i i i无法进行( X i X_i Xi Y i Y_i Yi) → ( X i + 1 X_i+1 Xi+1 Y i Y_i Yi)的行动;若 f i , 3 = 1 f_{i,3}=1 fi,3=1,则代表机器人 i i i可以进行( X i X_i Xi Y i Y_i Yi) → ( X i + 1 X_i+1 Xi+1 Y i Y_i Yi)的行动。
  • f i , 4 = 0 f_{i,4}=0 fi,4=0,则代表机器人 i i i无法进行( X i X_i Xi Y i Y_i Yi) → ( X i X_i Xi Y i + 1 Y_i+1 Yi+1)的行动;若 f i , 4 = 1 f_{i,4}=1 fi,4=1,则代表机器人 i i i可以进行( X i X_i Xi Y i Y_i Yi) → ( X i X_i Xi Y i + 1 Y_i+1 Yi+1)的行动。

当机器人收到一个坐标时它会自动进行寻路并前往。
现在请找到一个坐标,使得所有的机器人在收到坐标之后都可以到达那个坐标。

如果存在这个坐标则输出" 1 X Y 1 X Y 1XY",其中 ( X , Y ) (X,Y) (X,Y)为你所找到的那个坐标。
如果不存在则输出0。

思路

十分简单的思维题。
我们只需要找到所有机器人的活动范围的交集部分,这个部分内的所有点都可以是答案。

在这里插入图片描述

这是第二个样例中三个机器人的活动范围,图画的丑了点,就乎着看吧。
处在 ( 1 , 5 ) (1,5) (1,5)处的机器人可以向所有方向行动,所以它的活动范围就是整个二维图;
处在 ( 2 , 5 ) (2,5) (2,5)处的机器人只能上下移动,所以它的活动范围就是 x = 2 x=2 x=2这条红色直线;
处在 ( 3 , 5 ) (3,5) (3,5)处的机器人只能向左移动,所以它的活动范围就是绿色的直线;
而这三个机器人活动范围的交集就是点 ( 2 , 5 ) (2,5) (2,5)。所以答案是 ( 2 , 5 ) (2,5) (2,5)

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+100;

int a[maxn][10];

int main()
{
    ios::sync_with_stdio(false);
    int q;
    cin>>q;
    while(q--){
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
            for(int j=0;j<6;j++)
            cin>>a[i][j];
        //最后答案的X、Y的上限是100000
        int mxx=100000,mix=-100000;
        int may=100000,miy=-100000;
        for(int i=0;i<n;i++){
            if(a[i][2]==0) mix=max(a[i][0],mix);
            if(a[i][3]==0) may=min(a[i][1],may);
            if(a[i][4]==0) mxx=min(a[i][0],mxx);
            if(a[i][5]==0) miy=max(a[i][1],miy);
        }
        if(mxx>=mix&&may>=miy){
            cout<<"1 "<<mxx<<" "<<may<<endl;
        }
        else cout<<"0"<<endl;
    }
}

D1 - RGB Substring (easy version) (暴力)

比赛链接:https://codeforces.com/contest/1196/problem/D1

题目大意

给出一个字符串s。
问你至少需要改变字符串 s s s中的几个字符,才能使得字符串 s s s的一个长度为 k k k的子串 s ′ s' s同时也是" R G B R G B R G B R G B R G . . . RGBRGBRGBRGBRG... RGBRGBRGBRGBRG..."的子串?

本题中字符串 s s s的长度最多为 2000 2000 2000

思路

2000 2000 2000的长度? 2 2 2秒?
这意味着什么不用我多说了吧,暴力干它就完事了。
不过要注意的是s’的形式有三种:RGBRGBR...GBRGBRGBR..BRGBRGBR...,符合任意一种即可。

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+100;

int main()
{
    ios::sync_with_stdio(false);
    int q;
    cin>>q;
    while(q--){
        int n,k;
        int minx=inf;
        string ss;
        cin>>n>>k;
        cin>>ss;
        for(int i=0;i<=n-k;i++)
        {
            string s=ss.substr(i,k);
            string words="RGB";
            for(int j=0;j<3;j++){
                int l=j,cnt=0;
                string str="";
                while(cnt<k){
                    str+=words[l];
                    l++;
                    if(l==3) l=0;
                    cnt++;
                }
                int x=0;
                for(int z=0;z<k;z++)
                    if(s[z]!=str[z])
                    x++;
                minx=min(x,minx);
            }
        }
        cout<<minx<<endl;
    }
}

D2 - RGB Substring (hard version)(前缀和)

比赛链接:https://codeforces.com/contest/1196/problem/D2

题目大意

给出一个字符串s。
问你至少需要改变字符串 s s s中的几个字符,才能使得字符串 s s s的一个长度为 k k k的子串 s ′ s' s同时也是" R G B R G B R G B R G B R G . . . RGBRGBRGBRGBRG... RGBRGBRGBRGBRG..."的子串?

本题中字符串 s s s的长度最多为 2 e 5 2e5 2e5

思路

出题人:“就你搁这暴力是吧?挺猖狂啊?”

在这里插入图片描述
数据量加大了而已,有什么好怕的。
既然正着想(还差多少个字符才符合)行不通,那么我反着想(已经有多少个字符是符合的)总没问题吧。

首先我们要知道,如果 a ′ a' a a a a的子串, a ′ ′ a'' a a ′ a' a的子串,那么根据继承关系, a ′ ′ a'' a也是 a a a的子串
那我们就创建三个不同的" R G B R G B R G B R G B R G . . . RGBRGBRGBRGBRG... RGBRGBRGBRGBRG..."的子串:

1.RGBRGBR...
2.GBRGBRG...
3.BRGBRGB...

然后我们再设定一个前缀和数组sumsum[i][j]代表的是字符串s的前j个字符中与上面的第i个字符串前j个字符有多少个字符是同位置并相同的个数

字符串s:BGGGG
 一号串:RGBRG
  sum :01112

这样我们就可以求出字符串s中最多可以匹配上的字符的个数,再用k减去不就是答案吗?

AC代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;

string words="RGB";
int sum[5][maxn];

int main()
{
    ios::sync_with_stdio(false);
    int q;
    cin>>q;
    while(q--)
    {
        int n,k;
        int maxx=-1;
        string ss;
        string str[4];
        cin>>n>>k;
        cin>>ss;
        for(int j=0; j<3; j++)
        {
            int l=j,cnt=0;
            str[j]="";
            while(cnt<n)
            {
                str[j]+=words[l];
                l++;
                if(l==3)
                    l=0;
                cnt++;
            }
        }
        sum[0][0]=sum[1][0]=sum[2][0]=0;
        for(int i=0;i<n;i++){
            if(ss[i]==str[0][i]) sum[0][i+1]=sum[0][i]+1;
            else sum[0][i+1]=sum[0][i];
            if(ss[i]==str[1][i]) sum[1][i+1]=sum[1][i]+1;
            else sum[1][i+1]=sum[1][i];
            if(ss[i]==str[2][i]) sum[2][i+1]=sum[2][i]+1;
            else sum[2][i+1]=sum[2][i];
        }

        for(int i=1;i<=n-k+1;i++){
            maxx=max(maxx,sum[0][i+k-1]-sum[0][i-1]);
            maxx=max(maxx,sum[1][i+k-1]-sum[1][i-1]);
            maxx=max(maxx,sum[2][i+k-1]-sum[2][i-1]);
        }
        cout<<k-maxx<<endl;
    }
}

后话

感谢阅读,希望能对你产生一点用处。

以下台词取自《银魂》第80集:
(银八混打,帅呆了(❤´艸`❤))

在这里插入图片描述

"新八:笑容背后所承受的重担,"
"新八:如果你知道,为什么不看看老姐现在的神情!"
"银时:恋爱的形式,"
"银时:连对方的感觉都不知道,有什么资格说那种恶心的话!"
"新八:超越男女的世界,"
"银时:那种东西谁知道啊笨蛋!"
"新八:让喜欢的人哭的家伙,"
"银时:不管是男人还是女人,"
"银时/新八:都是混账啊笨蛋!"

吾日三省吾身:日更否?刷题否?快乐否?
更新了,但不是日更;已刷;激动
不破不立,EDG加油!

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值