cf edu #128 Div2

本文介绍了三道Codeforces竞赛题目,涉及最小数组构造、机器人移动策略和二进制字符串优化。第一题要求根据数值范围构建最小数组,第二题探讨如何使机器人团队达到目标区域,第三题展示了数学技巧在处理字符串问题中的应用。
摘要由CSDN通过智能技术生成

cf edu #128 Div.2

A. Minimums and Maximums

  • 题意

​ 给你数组中最小值的个数范围[l1,r1],以及最大数的个数范围[l2,r2],让你据此造一个size最小的数组,并输出最小size

  • 题解

​ 约定l1<=l2,

	1. 如果数组最大值和最小值都是一个数,即l2在[l1,r1]之间,那么可以让这个数组size为l2,因为此时既满足了最大数值的个数范围又满足了最小数值的个数范围。
	2. 如果数组最大值和最小值不是一个数,即l2不在[l1,r1]之间,那么此时让size为l1+l2满足最大与最小的数值的范围。
  • 代码
#include <iostream>
 
using namespace std;
 
int main()
{
    int n;
    int l1,r1,l2,r2;
    cin>>n;
    while(n--){
        cin>>l1>>r1>>l2>>r2;
        if(l2<l1){//固定l1是小的那个,方便讨论
            swap(l1,l2);
            swap(r1,r2);
        }
        
        if(l1<=l2&&r1>=l2)cout<<l2<<'\n';
        if(r1<l2)cout<<l1+l2<<'\n';
    }
    return 0;
}

B. Robots

  • 题意

​ 给定一个只含有字符’E’‘R’二维数组,你可以让所有的’R’同时向上下左右四个方向移动,让你判断这个二维平面是否能有’R’ 移动到左上角位置同时没有’R’跑出边界

  • 题解

​ 通过测试数据可以得到必胜和必输的两个充要条件,都可以用来做

1. 必胜的充要条件:必须有一个'R'在所有的'R'中是横纵坐标都是最小的
2. 必输的充要条件:出现了如下图的结构时,一定输[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fBBUIqXJ-1652579296655)(/Users/chenyanling/Desktop/C32726A9-6B7D-4D44-879E-D81F491BCDE8.jpeg)]
  • 代码
//必胜充要条件
#include <iostream>

using namespace std;

int main()
{
    int t;
    cin>>t;
    while(t--){
        char a[6][6];
        int n,m;
        cin>>n>>m;
        
        int x=0x3f3f3f3f,y=0x3f3f3f3f;//分别记录所有R的最小横坐标和最小纵坐标
        for (int i = 0; i < n; i ++ ){
            for (int j = 0; j < m; j ++ ){
                cin>>a[i][j];
                
                if(a[i][j]=='R'){
                    x=min(x,i);
                    y=min(y,j);
                }
            }
        }
        
        cout<<(a[x][y]=='R' ? "YES":"NO")<<'\n';//如果有最小横纵坐标的R,那么说明可以胜利
    }
    return 0;
}







//必输充要条件
#include <iostream>
 
using namespace std;
 
int main()
{
    int t;
    cin>>t;
    while(t--){
        char a[6][6];
        int n,m;
        cin>>n>>m;
        
        int x1=0x3f3f3f3f,y1=0,flag=0;//记录最上且最左的R的横纵坐标,flag记录有没有出现图中结构
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                cin>>a[i][j];
                
                if(a[i][j]=='R'){//因为有些上下左右顺序在输入时已经确定,故下面的坐标比较有简化
                    if(i<x1)x1=i,y1=j;
                    if(j<y1)flag=1;//出现必输结构
                }
            }
        }
        
        cout<<(flag?"NO":"YES")<<'\n';
    }
    
    return 0;
}

C. Binary String(数学转换太妙了

  • 题意

    给定一个01字符串s,选定一个子串c让如下式子最小(s1,c0,c1分别为s中1的个数,c中0和1的个数)
    m a x ( C 0 , S 1 − C 1 ) max(C_0,S_1-C_1) max(C0,S1C1)

  • 题解

    对上述式子数学变换一下
    m a x ( C 0 , S 1 − C 1 ) = m a x ( C 0 + C 1 , S 1 ) − C 1 max(C_0,S_1-C_1)=max(C_0+C_1,S_1)-C_1 max(C0,S1C1)=max(C0+C1,S1)C1
    让子串c的长度为len,那么式子变成
    m a x ( l e n , S 1 ) − C 1 max(len,S_1)-C_1 max(len,S1)C1
    既然要求最小的max,那么接下来分类讨论一下

    1. l e n ≥ S 1 → m a x ( l e n , S 1 ) − C 1 = l e n − C 1 = C 0 len\geq S_1\to max(len,S_1)-C_1=len-C_1=C_0 lenS1max(len,S1)C1=lenC1=C0

      我们希望子串中0尽量少,那么子串c越短则0越少,故让len=s1

    2. l e n ≤ S 1 → m a x ( l e n , S 1 ) − C 1 = S 1 − C 1 len\leq S_1\to max(len,S_1)-C_1=S_1-C_1 lenS1max(len,S1)C1=S1C1

      我们希望子串中1尽量大,那么子串C越长则1越多,故让len=s1

    由讨论得,子串c的长度一定为s1,那么答案就是子串中0最少的方案

  • 代码

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 2e5+5;

int s[N];//前缀和字符串中0的数量

int main()
{
    int t;
    cin>>t;
    while (t -- ){
        string str;
        cin>>str;
        
        int n=str.length();//字符串长度
        str="?"+str;//因为要预处理前缀和,所以要会从1开始算,所以字符串整个向后移一位
        for (int i = 1; i <= n; i ++ )s[i]=s[i-1]+(str[i]=='0');//预处理
        int len=count(str.begin(),str.end(),'1');//由推论得子串长度等于s1,求s1的大小
        
        int res=len;//随便初始化
        for(int i=len;i<=n;i++)res=min(res,s[i]-s[i-len]);//从所有长度为len的子串中找0最少的子串,其0的数量即为答案
        
        cout<<res<<'\n';
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值