AtCoder Beginner Contest 386(补题)
AtCoder Beginner Contest 386
C - Operate 1
思路
简单的条件判断题
代码
#include <bits/stdc++.h> typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; void solve(){ int k; std::string s, t; std::cin >> k >> s >> t; int n = s.size(), m = t.size(), ans = 0; if (n == m){ for (int i = 0; i < n; i++){ if (s[i] != t[i]){ k -= 1; if (k < 0) { break; } } } if (k < 0) ans = 0; else ans = 1; }else if (n == m + 1){ int index = 0; for (int i = 0; i < n; i++){ if (s[i] == t[index]){ index++; } } if (index == m){ ans = 1; }else{ ans = 0; } }else if (m == n + 1){ int index = 0; for (int i = 0; i < m; i++){ if (t[i] == s[index]) index++; } if (index == n){ ans = 1; }else{ ans = 0; } }else{ ans = 0; } std::cout << (ans == 0 ? "No\n" : "Yes\n"); } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
D - Diagonal Separation
思路
通过观察,可以发现,最后的棋盘中,黑色格子形成了一种阶梯状(左上三角形)的结构。也就是说,一个黑格子的左上的所有格子,必须都是黑格子。所以,如果一个已染色的黑格子的左上有白格子,那么一定是No。因此,“染色的黑格子的左上没有染色的白格子”是一个必要条件。
那么它是不是充分条件呢?是!只要我把所有的黑格子的左上全染黑,就得到了一个可行方案,因此该条件是充分条件,只要满足了,就可以输出Yes。
因此,只需检测每个黑格子的左上有没有白格子即可。暴力检测复杂度M^2会超时,可以考虑先把所有格子按照行升序排序,如果行相同就按照列升序,依次处理。
评述
最近在学离散化,看到这个N的范围还以为是离散化,上来就是做,结果题目都没有理解。【哭了】
代码
#include <bits/stdc++.h> typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; struct node{ int x, y; bool is_b; }; bool operator<(node a, node b){ return a.x != b.x ? a.x < b.x : a.y < b.y; } void solve(){ int n, m; std::cin >> n >> m; std::vector<node> v(m); for (int i = 0; i < m; i++){ int a, b; char c; std::cin >> a >> b >> c; v[i] = {a, b, c == 'B'}; } std::sort(v.begin(), v.end()); int mn = n + 1; for (auto nd : v){ if (nd.is_b){ if (nd.y >= mn){ std::cout << "No\n"; return; } }else{ mn = std::min(mn, nd.y); } } std::cout << "Yes\n"; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
E - Maximize XOR
思路
根据题目的所给的
,所以直接枚举所以情况就行。时间复杂度是 ,但是考虑到 k 有可能很大,导致TLE。我们知道 ,所以可以通过比较 k 和 n/2 的大小关系选择两种枚举方案,一种是在 n 个数中选 k 个,一种是 n 个数都选了,其中 n - k 个数需要去掉
代码
#include <bits/stdc++.h> typedef std::pair<int, int> pii; #define INF 0x3f3f3f3f #define MOD 998244353 using i64 = long long; const int N = 1e5+5; void solve(){ int n, k; std::cin >> n >> k; std::vector<i64> v(n+1); for (int i = 1; i <= n; i++){ std::cin >> v[i]; } i64 ans = 0; auto dfs = [&](auto self, int pos, int left, i64 sum) -> void { if (left == 0){ ans = std::max(ans, sum); return; } for (int i = pos + 1; i <= n; i++){ self(self, i, left - 1, sum ^ v[i]); } }; if (k < n / 2) dfs(dfs, 0, k, 0); else{ i64 presum = 0; for (int i = 1; i <= n; i++) presum ^= v[i]; dfs(dfs, 0, n - k, presum); } std::cout << ans << '\n'; } signed main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2); int t = 1, i; for (i = 0; i < t; i++){ solve(); } return 0; }
F - Operate K
思路:dp + 优化
这道题目是一道经典 DP 问题:
假设 S 的长度是 N,T 的长度是 M
设代表将 改成和 一样,最少需要几次操作。
这样只需要判断是否 <= K 即可。
转移方程:
= min( 删除一个字符,即
添加一个字符,即
更改一个字符,即
这两个字符本身就匹配,要求
,此时对应
)
这样做的复杂度是的,会超时。 但是注意到 K 很小,代表着
中,如果 ,那么需要的操作次数一定比 K 多,也即,此时 一定 > k,计算它没有意义。
所以,我们只考虑的 dp。这样的复杂度就是 O(NK) 的, 的值被 约束,可行的 的范围是 ,所以直接从这个范围的起点开始枚举 就行了
评述
相比于做对这道题,学会这道题的优化技巧更加重要
代码
#include <bits/stdc++.h> using namespace std; int k; int n, m; string s, t; int f[500010][60]; // f[i][x] 是 dp[i][i-30+x] int get_dp(int i, int j) { // 输入 i, j,返回 dp[i][j] if (abs(i-j) > k) return 0x3f3f3f3f; return f[i][j-i+30]; } void solve() { memset(f, 0x3f, sizeof(f)); f[0][30] = 0; // 对应 dp[0][0] for (int i = 1; i <= k; ++i) f[0][30+i] = i; // f[0][30+i] 对应 dp[0][i] for (int i = 1; i <= k; ++i) f[i][30-i] = i; // f[i][30-i] 对应 dp[i][0] for (int i = 1; i <= n; ++i) for (int x = 0; x < 60; ++x) { int j = i-30+x; if (j <= 0 || j > m) continue; int cur_dp = 0x3f3f3f3f; cur_dp = min(cur_dp, get_dp(i-1, j)+1); cur_dp = min(cur_dp, get_dp(i, j-1)+1); cur_dp = min(cur_dp, get_dp(i-1, j-1)+1); if (s[i] == t[j]) cur_dp = min(cur_dp, get_dp(i-1, j-1)); f[i][x] = cur_dp; } } int main() { cin >> k; cin >> s >> t; n = s.length(); m = t.length(); s = " " + s; t = " " + t; solve(); puts(get_dp(n, m) <= k ? "Yes" : "No"); return 0; }
本文作者:califeee
本文链接:https://www.cnblogs.com/califeee/p/18644144
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步