AtCoder Beginner Contest 285
A - Edge Checker 2 (abc285 a)
题目大意
给定如下一棵树。
给定 ,问两者是否有连边。
解题思路
观察数可发现其为二叉树,两者有连边当且仅当或
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int a, b; cin >> a >> b; if (a * 2 != b && a * 2 + 1 != b) cout << "No" << '\n'; else cout << "Yes" << '\n'; return 0; }
B - Longest Uncommon Prefix (abc285 b)
题目大意
给定一个长度为字符串,对于每个 ,找到最大的使得
解题思路
数据范围不大,暴力即可。
即对于每个, 枚举 从 到第一个 为止。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; string s; cin >> n >> s; auto solve = [&](int x){ int ans = 0; while(ans < n - x){ if (s[ans] == s[ans + x]) break; ++ ans; } return ans; }; for(int i = 1; i < n; ++ i){ cout << solve(i) << '\n'; } return 0; }
C - abc285_brutmhyhiizp (abc285 c)
题目大意
有一堆字符串,其字典序顺序为:
- 'a', 'b', ..., 'z', 'aa', 'ab', ..., 'az', 'ba', 'bb', ..., 'bz', ..., 'za', 'zb', ..., 'zz', 'aaa', 'aab', ..., 'aaz', 'aba', 'abb', ..., 'abz', ..., 'zzz', 'aaaa', ...
现给定其中一个字符串,问其字典序大小。
解题思路
这题是abc171 c的反过来形式。
每个位置,以a
-z
的26为一循环,但第一次循环时还有一个0
(a
可以看成是0a
)。所以 a
应当看成数字。
因此高位转低位时,进位时,但末尾数字减去'A'后还要加一。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s; cin >> s; LL ans = 0; for(auto &i : s){ ans = ans * 26 + (i - 'A' + 1); } cout << ans << '\n'; return 0; }
D - Change Usernames (abc285 d)
题目大意
给定对字符串 。表示有 个人,原本叫 ,现在需要改名为 。
你现在要处理该请求,每次只能改一个人的名,问改名过程中会不会出现重名,即一个人改成了,但还有另一个还没改名的
解题思路
字符串改成 ,则从 连一条有向边到 。
如果存在一个环,则改名过程必定重名。
有向边判环的方法即拓扑排序。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; vector<string> s(n), t(n); set<string> qwq; map<string, int> tr; for(int i = 0; i < n; ++ i){ cin >> s[i] >> t[i]; qwq.insert(s[i]); qwq.insert(t[i]); } int cnt = 0; for(auto &i : qwq){ tr[i] = cnt; ++ cnt; } vector<int> du(cnt); vector<vector<int>> edge(cnt); for(int i = 0; i < n; ++ i){ int u = tr[s[i]]; int v = tr[t[i]]; edge[u].push_back(v); du[v] ++; } queue<int> team; for(int i = 0; i < cnt; ++ i){ if (du[i] == 0) team.push(i); } while(!team.empty()){ auto u = team.front(); -- cnt; team.pop(); for(auto &v : edge[u]){ du[v] --; if (du[v] == 0) team.push(v); } } if (cnt) cout << "No" << '\n'; else cout << "Yes" << '\n'; return 0; }
E - Work or Rest (abc285 e)
题目大意
一周有天。 给定一个长度为的数组 。
你需要指定 至少一天为休息日,其余为工作日。要求最大化工作日的产能。
一个工作日的产能定义为,其中 是该日距离过去最近的休息日的天数, 是该日距离未来最近的休息日天数。注意周与周之间是连贯的,第一周的第一天的过去可以是上一周。
解题思路
如果不考虑连贯的影响,即认为一周是独立的,可以设表示第 天为休息日的情况下最大的产生值。转移时枚举上一次休息日的天数 。
观察 ,中间 到 的产能值,即为 ,即下标是一个先递增后递减的规律,就是一个 的前缀和的两倍,根据奇偶性可能多出一个。这样转移可以 。复杂度就是
但是一周并不是独立的,这样的方程具有后效性,归根结底就在于我们不知道一周第一次的休息日的日子,无法算出该日子之前和最后一个休息日之后的这几天的产能贡献。但如果设表示第一次休息日在第 天,然后在第 天也是休息日的最大产能,其复杂度为 。
但是,注意到天与天之间没有区别的,意思就是说,如果我们确定了第一次休息日的天数,以及最后一次休息日的天数,那这两个休息日之间,里面休息日任意选,获得的产生最大值,其实就是 。
因此我们预处理 ,然后枚举第一次休息日和最后一次休息日 所在天数,那答案 加上前 天和后 天工作日的产能贡献了。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; vector<LL> a(n); for(auto &i : a) cin >> i; vector<LL> sum(n); partial_sum(a.begin(), a.end(), sum.begin()); vector<LL> dp(n + 1, 0); auto solve = [&](int len){ int dig = (len & 1); int half = (len >> 1); LL tmp = 0; if (half) tmp += 2ll * sum[half - 1]; if (dig) tmp += a[half]; return tmp; }; for(int i = 1; i <= n; ++ i){ for(int j = 0; j < i; ++ j){ dp[i] = max(dp[i], dp[j] + solve(i - j - 1)); } } LL ans = 0; for(int i = 0; i < n; ++ i) for(int j = i; j < n; ++ j){ ans = max(ans, dp[j - i] + solve(i + n - j - 1)); } cout << ans << '\n'; return 0; }
F - Substring of Sorted String (abc285 f)
题目大意
给定一个字符串,定义字符串 为串 各字母从小到大排序的字符串。进行 次操作,操作分两种:
1 x c
,令2 x y
,问是不是 串的一个子串
解题思路
对于询问,其等价于:串是串 的子串,说明
- 其串是递增的
- 除首字母和末字母之外,中间的字母出现次数都是串 中出现的次数
初步想法是预处理出数组表示第 个字母的左边、右边第一个非该字母的位置。
对于一个询问 ,就是中间字母,其长度和各字母的出现次数都必须符合上述要求,也就是说这段字符串必须是确定的某一个,可以用字符串hash来判断,而由于操作一涉及到修改(该确定的字符串的hash可以在的复杂度计算出),因此需要用线段树hash的方式维护其hash值。
同时数组同样也要维护,考虑操作一的影响,这涉及到区间修改,需要用线段树维护,但逻辑稍微复杂,写起来比较麻烦。
神奇的代码
G - Tatami (abc285 g)
题目大意
给定一个的网格,格子上有 1 2 ?
这三个符号,要求用和 (可旋转)的矩形覆盖。其中 1
的格必须被 的格子覆盖, 2
的格必须被的格子覆盖, ?
的则随意。
问是否存在一种方案。
解题思路
<++>
神奇的代码
Ex - Avoid Square Number (abc285 h)
题目大意
给定和一个长度为 的序列 ,要求求一个长度为 的正整数序列的数量,满足:
- 所有元素都不是平方数
- 所有元素的乘积为
其中 是第 小的质数。
解题思路
<++>
神奇的代码
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/17054546.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2017-01-16 二分图匹配之最佳匹配——KM算法
2017-01-16 二分图匹配之最大匹配——匈牙利算法