题目传送门 A
题目大意:
一个数组中存在 [ l 1 , r 1 ] [ l1, r1 ] [l1,r1] 个最小值和 [ l 2 , r 2 ] [ l2, r2 ] [l2,r2]个最大值,求这个数组中元素的最小个数。
思路:
朴
素
做
法
:
朴素做法:
朴素做法:
分为三种情况,
(
1
)
(1)
(1) 第二个区间在第一个区间右边,
(
2
)
(2)
(2) 第二个区间和第一个区间重叠一部分,
(
3
)
(3)
(3) 第二个区间在第一个区间左边,
分析交集,输出即可
简
单
做
法
:
简单做法:
简单做法:
(
1
)
(1)
(1) 若两个区间独立,则将
l
1
+
l
2
l1 + l2
l1+l2作为
r
e
s
res
res输出
(
2
)
(2)
(2) 若两个区间不独立,则一定存在
l
2
l2
l2 或者
l
1
l1
l1 在另一个区间中,可分析知道,
m
a
x
(
l
1
,
l
2
)
max(l1, l2)
max(l1,l2) 一定为两者重叠部分的最小值,则将
m
a
x
(
l
1
+
l
2
)
max(l1 + l2)
max(l1+l2)作为
r
e
s
res
res输出
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 2e5+10;
/*简单做法
void solve() {
if(r2 < l1 || r1 < l2) cout << l1 + l2 << endl;
else cout << max(l1, l2) << endl;
}
*/
void solve()
{
int l1, r1, l2, r2;
scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
int res = 0;
if(l2 > r1) res = l1 + l2;
else if(l2 <= r1 && l2 >= l1) res = l2;
else if(l2 < l1 && r2 >= l1) res = l1;
else res = l1 + l2;
printf("%d\n", res);
}
int main()
{
int T;
scanf("%d", &T);
while(T -- )
solve();
return 0;
}
题目传送门 B
题目大意:
给定二维字符串,包含
E
E
E
R
R
R,两种字符;可以将
R
R
R 字符上下左右移动,但移动时必须所有的
R
R
R 字符一起动。
问:能否将任意一个
R
R
R 移动到左上角
(
0
,
0
)
(0, 0)
(0,0) 的位置,同时其他的
R
R
R 不在移动的过程中超出边界,能输出
Y
E
S
YES
YES ,反之输出
N
O
NO
NO 。
思路:
同时查找最左边,和最上边的
R
R
R 字符的坐标,比较坐标是否相等
代码如下:
#include <bits/stdc++.h>
// 将 PII 的第一个数重命名 为 x
// 第二个数重命名为 y ,便于理解代码
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 2e5+10;
void solve()
{
int n, m;
scanf("%d %d", &n, &m);
string s[6];
PII mi1 = {6, 6}, mi2 = {6, 6};
for(int i = 0; i < n; i ++ )
cin >> s[i];
for(int i = 0; i < n; i ++ )
{
for(int j = 0; j < m; j ++ )
{
if(s[i][j] == 'R' && j < mi1.x) mi1 = {j, i};
if(s[i][j] == 'R' && i < mi2.y) mi2 = {j, i};
}
}
if(mi1 != mi2) puts("NO");
else puts("YES");
}
int main()
{
int T;
scanf("%d", &T);
while(T -- )
solve();
return 0;
}
题目传送门 E
题目大意:
多实例
给定一个数,表示字符串长度,给定两行字符串,包含字符星
‘
∗
’
‘*’
‘∗’ 和字符点
‘
.
’
‘.’
‘.’,目的是变成一个字符星,
条件:当字符星相邻时,其中一个字符星可以移动到零一个字符星的位置,并吞噬另外一个字符星
思路:
先限制字符星的范围,查找最左边的字符星,和最右边的字符星,锁定含字符星的区间,开始计算
(
1
)
(1)
(1) 假设
n
n
n 字符星都相邻时,我们最少需要
n
−
1
n-1
n−1 步才能吞噬的只剩一个字符星,所以先将答案加上所有字符星的个数,最后在减去
1
1
1
(
2
)
(2)
(2) 然后我们判断每一列的情况
同一列分为三种情况 两个都是星,一个星一个点,两个都是点
当遇见上下两格都是字符点时,我们的字符星不得不多走一步,
r
e
s
res
res++
当遇见两个都是星的情况,我们得向上或向下走一步,但在第一步我们已经 预处理过,此处就不用预处理,
同时将含有星的列加入后面应该处理的字符中
(
3
)
(3)
(3) 此时的 ta,tb 字符串的每一列中都含有字符星,我们可以考虑到,
如果为这种情况
′
∗
′
′
.
′
′
.
′
′
∗
′
(1)
\begin{matrix} '*' & '.' \\ '.' & '*' \end{matrix} \tag{1}
′∗′′.′′.′′∗′(1)
或者
′
.
′
′
∗
′
′
∗
′
′
.
′
(2)
\begin{matrix} '.' & '*' \\ '*' & '.' \\ \end{matrix} \tag{2}
′.′′∗′′∗′′.′(2)
即,两个字符星处于对角线的情况,此时需要多移动一步才能到达另一个字符星的位置达成吞噬的效果
代码如下:
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1010;
int n;
int T;
void solve()
{
int n;
string a, b;
string ta = "", tb = "";
cin >> n >> a >> b;
int res = 0;
int l, r;
for(int i = 0; i < n; i ++ )
{
if(a[i] == '*' || b[i] == '*')
{
l = i;
break;
}
}
for(int i = n-1; i >= 0; i -- )
{
if(a[i] == '*' || b[i] == '*')
{
r = i;
break;
}
}
for(int i = l; i <= r; i ++ )
{
if( a[i] == '*') res ++;
if( b[i] == '*') res ++;
if( a[i] == '.' && b[i] == '.' ) res ++;
else ta += a[i], tb += b[i];
}
for(int i = 0; i < ta.size() - 1; i ++ )
{
if( (ta[i] == '.' && tb[i+1] == '.') || (tb[i] == '.' && ta[i+1] == '.') )
{
res ++;
ta[i] = ta[i+1] = tb[i] = tb[i+1] = '*';
}
}
cout << res - 1 << endl;
return;
}
int main()
{
scanf("%d", &T);
while(T -- )
solve();
return 0;
}