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 ) (r,c) ( r , c ) 没被毁掉,直接标记为毁掉即可,否则就要找到上下左右四个方向上最近的墙并摧毁。
重点在于如何找到某一个方向上最近的墙。 一开始想复杂了:用二维树状数组维护二维前缀和,进行单点更新和区间查询,就能知道某一区域没被毁的格点数量;给定格点后,可以二分距离找到最近的没被毁的格点,用前缀和检查距离内是否有未被毁格点。 实际上用 set
维护每行每列未被毁的格点即可。需要注意的是 set
坑点很多:
erase
后迭代器失效,不能再访问数据;
要判断 set
是否为空;
注意 begin()
和 end()
的特判。