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() 的特判。
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int h, w, q;
vector<set<int>> remained_row;
vector<set<int>> remained_col;
vector<vector<bool>> vis;
int main()
{
cin >> h >> w >> q;
remained_row.resize(h + 1);
remained_col.resize(w + 1);
vis.resize(h + 1, vector<bool>(w + 1, true));
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++) {
remained_row[i].emplace(j);
}
}
for (int j = 1; j <= w; j++) {
for (int i = 1; i <= h; i++) {
remained_col[j].emplace(i);
}
}
while (q--) {
int r, c;
scanf("%d%d", &r, &c);
if (vis[r][c]) {
vis[r][c] = false;
remained_row[r].erase(remained_row[r].find(c));
remained_col[c].erase(remained_col[c].find(r));
} else {
if (!remained_row[r].empty()) {
auto R = remained_row[r].upper_bound(c);
if (R != remained_row[r].end()) {
vis[r][*R] = false;
remained_col[*R].erase(r);
remained_row[r].erase(R);
}
if (!remained_row[r].empty()) {
auto L = remained_row[r].upper_bound(c);
if (L != remained_row[r].begin()) {
L = prev(L);
vis[r][*L] = false;
remained_col[*L].erase(r);
remained_row[r].erase(L);
}
}
}

if (!remained_col[c].empty()) {
auto D = remained_col[c].upper_bound(r);
if (D != remained_col[c].end()) {
vis[*D][c] = false;
remained_row[*D].erase(c);
remained_col[c].erase(D);
}
if (!remained_col[c].empty()) {
auto U = remained_col[c].upper_bound(r);
if (U != remained_col[c].begin()) {
U = prev(U);
vis[*U][c] = false;
remained_row[*U].erase(c);
remained_col[c].erase(U);
}
}
}
}
}
int ans = 0;
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++) {
if (vis[i][j]) {
ans++;
}
}
}
cout << ans << endl;
return 0;
}