AtCoder Beginner Contest 370

A - Raise Both Hands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main()
{
int l, r;
cin >> l >> r;
if (l == r) {
cout << "Invalid" << endl;
} else if (l == 1) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
return 0;
}

B - Binary Alchemy

按照题目说的意思模拟即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
using namespace std;
const int MAX_N = 200;
int n;
int a[MAX_N][MAX_N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
scanf("%d", &a[i][j]);
}
}
int ans = 1;
for (int i = 1; i <= n; i++) {
if (ans >= i) {
ans = a[ans][i];
} else {
ans = a[i][ans];
}
}
cout << ans << endl;
return 0;
}

C - Word Ladder

贪心思路:每一次的修改后,所得到的字符串必须是所有修改选择中字典序最小的。由于数据范围不大,暴力即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <vector>
using namespace std;
const int MAX_N = 105;
struct Node {
string res;
int p;
};
list<int> pos;
vector<string> ans;
string s, t;
int n;
int main()
{
cin >> s >> t;
n = s.length();
for (int i = 0; i < n; i++) {
if (s[i] != t[i]) {
pos.push_back(i);
}
}
string cur = s;
while (!pos.empty()) {
vector<Node> nodes;
for (const int& p : pos) {
string temp = cur;
temp[p] = t[p];
nodes.emplace_back((Node) { temp, p });
}
sort(nodes.begin(), nodes.end(), [](const Node& a, const Node& b) { return a.res < b.res; });
cur = nodes[0].res;
ans.push_back(cur);
pos.remove(nodes[0].p);
}
cout << ans.size() << endl;
for (const string& s : ans) {
cout << s << endl;
}
return 0;
}

D - Cross Explosion

每次询问一个格点 (r,c)(r,c),如果 (r,c)(r,c) 没被毁掉,直接标记为毁掉即可,否则就要找到上下左右四个方向上最近的墙并摧毁。

重点在于如何找到某一个方向上最近的墙。 一开始想复杂了:用二维树状数组维护二维前缀和,进行单点更新和区间查询,就能知道某一区域没被毁的格点数量;给定格点后,可以二分距离找到最近的没被毁的格点,用前缀和检查距离内是否有未被毁格点。 实际上用 set 维护每行每列未被毁的格点即可。需要注意的是 set 坑点很多:

  • erase 后迭代器失效,不能再访问数据;
  • 要判断 set 是否为空;
  • 注意 begin()end() 的特判。