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,S1−C1) -
题解
对上述式子数学变换一下
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,S1−C1)=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,那么接下来分类讨论一下-
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 len≥S1→max(len,S1)−C1=len−C1=C0
我们希望子串中0尽量少,那么子串c越短则0越少,故让len=s1
-
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 len≤S1→max(len,S1)−C1=S1−C1
我们希望子串中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;
}