2021-11-05 训练

A - Three Piles of Candies

题意:

A和B分糖果,一共有三堆糖果,A可以先挑一堆糖果,B在挑一堆糖果,之后有平分操作,A和B希望糖果数相等,所以多的人会丢糖果,最后一堆糖果由A和B分,最后在执行平分操作,求A能得到的最大糖果数

思路:

先拿两堆后平分,第三堆糖果在分配后平分,因为糖果多的人会丢掉,所以求和除以2即可(记得关输入输出流或使用scanf)

代码:

#include<iostream>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    int t;;
    cin>>t;
    while(t--)
    {
        long long a,b,c,sum=0;
        cin>>a>>b>>c;
        sum=(a+b+c)/2;
        cout<<sum<<endl;
    }
}

B - Odd Sum Segments

题意:

q次查询,每次查询输入一个n和k,你有一个n个元素的数组,你需要把这个数组分成k段,如果每能分成k段的后每个段元素和为奇数,输出YES,并输出k个元素段的元素右侧端点位置,若分成k段的后每段元素和不为奇数输出NO

思路:

奇数+奇数=偶数,奇数+偶数=偶数,偶数+偶数=偶数
所以我们要找奇数的个数和位置,而当奇数的个数的奇偶性和k的奇偶性相同时才有可能使每个段元素和为奇数(你可以试试一些数5,6 | 7,9)当然奇数个数一定要大于等于k才可以。

代码:

#include<iostream>
using namespace std;
int a[210000];
int main()
{
    ios::sync_with_stdio(false);
    int t;;
    cin>>t;
    while(t--)
    {
        int n,k,sum=0;
        cin>>n>>k;
        for(int i=1; i<=n; i++)
        {
            cin>>a[i];
            if(a[i]%2==1)
                sum+=1; //奇数
        }
        if(sum%2==k%2&&sum>=k)
        {
            cout<<"YES"<<endl;
            for(int i=1,cnt=1; i<=n&&cnt<=k-1; i++)
            {
                if(a[i]%2==1)
                {
                     cout<<i<<" ";
                     cnt+=1;
                }
            }
            cout<<n<<endl;
        }
        else
            cout<<"NO"<<endl;
    }
}

C - Robot Breakout

题意:

q个查询,每个查询下输入一个n表示机器人的个数,之后n行x,y表示机器人的位置f1,f2,f3,f4为其左上右下四个方向是否可以移动,而每个方向都有对应的 f j = 1 或0 ,等于1代表可以移动,0则不能移动,求一个坐标(X,Y) 使得所有机器人都能够到达。而机器人停止移动当且仅当机器人到达了x,y或无法到达x,y。

思路:

我们根据输入的机器人位置可以确定界限,而根据每个机器人能走的方向可以缩小边界,当确定最小的边界时输出一个边界值即可。

代码:

#include<iostream>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    int t;;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int left=-1e5,down=-1e5;
        int right=1e5,up=1e5;
        while(n--)
        {
            int x,y,f1,f2,f3,f4;
            cin>>x>>y>>f1>>f2>>f3>>f4;
            if(f1==0)
                left=max(left,x);
            if(f4==0)
                down=max(down,y);
            if(f2==0)
                up=min(up,y);
            if(f3==0)
                right=min(right,x);
        }
        if(left>right||down>up)
            cout<<0<<endl;
        else
            cout<<1<<" "<<left<<" "<<up<<endl;
    }
}

D - RGB Substring (easy version)

题意:

q 组询问,每组给出一个长度为 n 的字符串与一个 "RGBRGBRGB..." 循环子串的长度 k,
现在要所给的长度为 n 的子串中选择一个长度为 k 的子串,对其进行任意次代价为 1 的更改,
即可将任意一个字符改为其他字符,使得这个子串与 "RGBRGBRGB..." 循环子串所匹配,求最小代价。

思路:

枚举把每个字符都修改为‘R‘ ’G‘ ’B’ ,开一个二维数组,记录更改的开销,
如果是他本身那么开销为0,其余两个都为1。初始化完了之后,用一个长度为k的滑动窗口,
右边收录一个字符,加上对应的开销,而左边删去一个字符,减去对应的开销。
同样是要枚举三种情况,每一次移动都结算一次最小值,最后得到的就是全局最优解。
那么这个窗口在初始化的时候,首先需要收录k个字符,先记录下他们的开销,以及开始和结束位置,接下来遍历整个串就行了,复杂度O(3*n)。

代码:

#include <bits/stdc++.h>
const int N = 1e6+10;
using namespace std;
int a[N][3]; // 记录每个字符的开销
map<char,int> mp; // 把字符映射成数字,便于处理

int main()
{
    int n,m;
    mp['R'] = 0;
    mp['G'] = 1;
    mp['B'] = 2;
    string s;
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>s;
        for(int i = 0 ; i < n ; i ++ ) // 初始化开销数组
        {
            a[i][mp[s[i]]] = 0;
            a[i][(mp[s[i]]+1)%3] = 1;
            a[i][(mp[s[i]]+2)%3] = 1;
        }
        int head1,head2,head3;
        int tail1,tail2,tail3;
        int sum1,sum2,sum3;
        head1 = 0 ;
        head2 = 1 ;
        head3 = 2 ;
        tail1 = 0 ;
        tail2 = 1 ;
        tail3 = 2 ;
        sum1 = sum2 = sum3 = 0;
        for(int i = 0 ; i < m ; i ++) // 初始化长度为K的窗口
        {
            sum1 += a[i][head1];
            sum2 += a[i][head2];
            sum3 += a[i][head3];
            head1 = (head1+1)%3;
            head2 = (head2+1)%3;
            head3 = (head3+1)%3;
        }
        int ans = min(sum1,min(sum2,sum3));
        for(int i = m ; i < n ; i ++) // 遍历数组,更新最小值
        {
            sum1 += a[i][head1];
            sum2 += a[i][head2];
            sum3 += a[i][head3];
            sum1 -= a[i-m][tail1];
            sum2 -= a[i-m][tail2];
            sum3 -= a[i-m][tail3];
            head1 = (head1+1)%3;
            head2 = (head2+1)%3;
            head3 = (head3+1)%3;
            tail1 = (tail1+1)%3;
            tail2 = (tail2+1)%3;
            tail3 = (tail3+1)%3;
            ans = min(min(ans,sum1),min(sum2,sum3));
        }
        cout << ans << endl;
    }
    return 0;
}

待更~~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值