AtCoder Beginner Contest 338

1|0A - Capitalized?


#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { string s; cin >> s; if (s[0] >= 'A' and s[0] <= 'Z') { for (int i = 1; i < s.size(); i++) { if (s[i] >= 'a' and s[i] <= 'z') continue; cout << "No\n"; return 0; } cout << "Yes\n"; } else { cout << "No\n"; } return 0; }

2|0B - Frequency


#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { string s; cin >> s; vi cnt(26); for( auto i : s ) cnt[i-'a'] ++; int t = *max_element(cnt.begin(), cnt.end()); for( int i = 0 ; i < 26 ; i ++ ){ if( t == cnt[i] ){ cout << (char)(i+'a'); return 0; } } return 0; }

3|0C - Leftover Recipes


#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { int n; cin >> n; vi q(n), a(n), b(n); for (auto &i: q) cin >> i; for (auto &i: a) cin >> i; for (auto &i: b) cin >> i; int res = 0; for (int x = 0, y; true; x++) { y = inf; auto c = q; for (int i = 0; i < n; i++) c[i] -= a[i] * x; if (*min_element(c.begin(), c.end()) < 0) break; for (int i = 0; i < n; i++) if( b[i] > 0 ) y = min(y, c[i] / b[i]); res = max(res, x + y); } cout << res << "\n"; return 0; }

4|0D - Island Tour


这题是个比较有意思的贪心。

首先我们可以在不删边的情况下求出最短的走法,然后可以在计算的过程中求出如果某一条边被删掉会导致哪些路径需要换方向,并且累加换方向要多走的长度。最终贪心的删掉多走长度最短的路即可。

#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi a(m); for (auto &i: a) cin >> i; vi b(n + 1); auto op = [n, &b](int l, int r) { if (l > r) swap(l, r); int t = abs((r - l) - (n - r + l)); if (t == 0) return; if (r - l < n - r + l) b[l] += t, b[r] -= t; else b[1] += t, b[l] -= t, b[r] += t; }; for (int i = 1; i < m; i++) op(a[i - 1], a[i]); for (int i = 1; i <= n; i++) b[i] += b[i - 1]; int t = 1; for (int i = 2; i <= n; i++) if (b[i] < b[t]) t = i; int res = 0; for (int i = 1; i < m; i++) { if (a[i] <= t and a[i - 1] <= t) res += abs(a[i] - a[i - 1]); else if (a[i] > t and a[i - 1] > t) res += abs(a[i] - a[i - 1]); else res += n - abs(a[i] - a[i - 1]); } cout << res << "\n"; return 0; }

5|0E - Chords


这题可以把所有的点对放在一维的数轴上,然后求一下有没有两个区间相交的情况。注意包含的情况不算相交。至于判断相交,我采用的是ST实现了求区间最值。

#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vector<pii> a(n); for (auto &[x, y]: a) { cin >> x >> y; if (x > y)swap(x, y); } sort(a.begin(), a.end()); int logN = log2(n) + 1; auto f = vector(n, vi(logN + 1)); for (int i = 0; i < n; i++) f[i][0] = a[i].second; for (int j = 1; j <= logN; j++) for (int i = 0; i + (1 << j) - 1 < n; i++) f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); auto calc = [f](int l, int r) -> int { int s = log2(r - l + 1); return max(f[l][s], f[r - (1 << s) + 1][s]); }; for (int i = 0, j, l, r; i < n; i++) { l = i, r = n - 1, j = i; for (int mid; l <= r;) { mid = (l + r) / 2; if (a[mid].first <= a[i].second) j = mid, l = mid + 1; else r = mid - 1; } if (calc(i, j) > a[i].second) { cout << "Yes\n"; return 0; } } cout << "No\n"; return 0; }s

但是赛后经过思考,我发现其实可以用括号匹配来实现,如果存在失配的情况就说明存在了交点。

#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vector<int> a(2 * n + 1); for (int i = 1, l, r; i <= n; i++) { cin >> l >> r; if (l > r) swap(l, r); a[r] = l; } stack<int> stk; for (int i = 1; i <= n * 2; i++) { if (a[i] == 0) stk.push(i); else { if (stk.top() == a[i]) stk.pop(); else { cout << "Yes\n"; return 0; } } } cout << "No\n"; return 0; }

6|0F - Negative Traveling Salesman


状压dp,f[i][j]表示当前访问过的点集是i且当前在j点的最小花费。

首先使用bellman-ford更新已经访问过的点集内部,然后再枚举点集向外走一步。

#include<bits/stdc++.h> using namespace std; #define int long long using vi = vector<int>; using i32 = int32_t; using pii = pair<int, int>; const int inf = 1e9, INF = 1e18; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vector<array<int, 3>> e(m); for (auto &[u, v, w]: e) cin >> u >> v >> w, u--, v--; vector f(1 << n, vi(n, INF)); for (int i = 0; i < n; i++) f[1 << i][i] = 0; for (int i = 0; i < (1 << n); i++) { for (bool flag = false; true; flag = false) { for (const auto &[u, v, w]: e) { if (f[i][v] <= f[i][u] + w) continue; flag |= true, f[i][v] = f[i][u] + w; } if (flag == false) break; } for (const auto &[u, v, w]: e) f[i | (1 << v)][v] = min(f[i | (1 << v)][v], f[i][u] + w); } int res = *min_element(f.back().begin(), f.back().end()); if (res >= inf) { cout << "No\n"; } else cout << res << "\n"; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/17993560.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(49)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示