(2024)第五届辽宁省大学生程序设计竞赛 (大连)

1|0A. 爱上字典


#include <bits/stdc++.h> using namespace std; using i64 = long long; using ui32 = unsigned int; using vi = vector<int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); string s, t = ""; getline(cin, s); s += ' '; set<string> cnt; for(int i = 0; i < s.size(); i ++) { if(s[i] >= 'a' and s[i] <= 'z') t += s[i]; else if(s[i] >= 'A' and s[i] <= 'Z') t += s[i] - 'A' + 'a'; else { if(t.empty()) continue; cnt.insert(t); t = ""; } } int n; cin >> n; for(; n; n --) { cin >> s; for(auto &c : s){ if(c >= 'A' and c <= 'Z') c = c - 'A' + 'a'; } cnt.erase(s); } cout << cnt.size() << "\n"; return 0; }

2|0B. 比分幻术


#include <bits/stdc++.h> using namespace std; using i64 = long long; using ui32 = unsigned int; using vi = vector<int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); string s; cin >> s; swap(s[0], s[2]); cout << s; return 0; }

3|0C. 插排串联


首先可以用dfs,求出所有节点的功率,然后贪心的给功率大的节点分配大的功率即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui32 = unsigned int; #define int i64 using vi = vector<int>; using pii = pair<int,int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi W(n + 1); W[0] = -1; vi b, node; vector<vi> e(n + 1); for(int i = 1, f; i <= n; i ++) { cin >> f >> W[i]; e[f].push_back(i); if(W[f] != -1) b.push_back(W[f]), W[f] = -1, node.push_back(f); } auto dfs = [&](auto self, int x) -> void { if(W[x] != -1) return; W[x] = 0; for(auto y : e[x]) { self(self, y); W[x] += W[y]; } return; }; dfs(dfs, 0); if(W[0] > 2200) { cout << "NO\n"; return 0; } ranges::sort(b); ranges::sort(node ,[&](const int &x, const int &y) -> bool { return W[x] < W[y]; }); for(int i = 0; i < b.size(); i ++) { if(b[i] >= W[node[i]]) continue; cout << "NO\n"; return 0; } cout << "YES\n"; return 0; }

4|0D. 都市叠高


看似求凸包,直径一定是一组点对,因此直接 dp 就好。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui32 = unsigned int; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int,int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vector<ldb> x(n + 1), y(n + 1); for(int i = 1, _x, _y; i <= n; i++) cin >> _x >> _y, x[i] = _x, y[i] = _y; vector<ldb> f(n + 1); for(int i = 1; i <= n; i ++) { f[i] = f[i - 1]; ldb maxx = 0; for(int j = i - 1; j >= 1; j --){ maxx = max(maxx, hypot(x[i] - x[j], y[i] - y[j])); f[i] = max(f[i], f[j - 1] + maxx); } } cout << fixed << setprecision(20) << f[n] << "\n"; return 0; }

5|0E. 俄式简餐


能够拼出来的基础方形有1×4,2×6,两种。

#include <bits/stdc++.h> using namespace std; using i64 = long long; using ui32 = unsigned int; using vi = vector<int>; void solve(){ int n, m, k = 0; cin >> n >> m; if((n * m) % 4 != 0) { cout << "NO\n"; return; } if(n == 2 and m == 2) { cout << "NO\n"; return; } vector g(n + 1, vi(m + 1)); if(n % 4 == 0){ for(int j = 1; j <= m; j ++) for(int i = 1; i <= n; i += 4) { k ++; g[i][j] = g[i + 1][j] = g[i + 2][j] = g[i + 3][j] = k; } } else if(m % 4 == 0) { for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j += 4) { k ++; g[i][j] = g[i][j + 1] = g[i][j + 2] = g[i][j + 3] = k; } } else if(m > 2) { for(int i = 1; i <= n; i += 2) { k ++; g[i][1] = g[i][2] = g[i][3] = g[i + 1][1] = k; k ++; g[i][4] = g[i][5] = g[i][6] = g[i + 1][6] = k; k ++; g[i + 1][2] = g[i + 1][3] = g[i + 1][4] = g[i + 1][5] = k; for(int j = 7; j <= m; j += 4) { k ++; g[i][j] = g[i][j + 1] = g[i][j + 2] = g[i][j + 3] = k; k ++; g[i + 1][j] = g[i + 1][j + 1] = g[i + 1][j + 2] = g[i + 1][j + 3] = k; } } } else if(n > 2){ for(int j = 1; j <= m; j += 2) { k ++; g[1][j] = g[2][j] = g[3][j] = g[1][j + 1] = k; k ++; g[4][j] = g[5][j] = g[6][j] = g[6][j + 1] = k; k ++; g[2][j + 1] = g[3][j + 1] = g[4][j + 1] = g[5][j + 1] = k; for(int i = 7; i <= n; i += 4) { k ++; g[i][j] = g[i + 1][j] = g[i + 2][j] = g[i + 3][j] = k; k ++; g[i][j + 1] = g[i + 1][j + 1] = g[i + 2][j + 1] = g[i + 3][j + 1] = k; } } } cout << "YES\n"; for(int i = 1; i <= n; i ++){ for(int j = 1; j <= m; j ++) { cout << g[i][j] << " "; } cout << "\n"; } return ; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); int t; std::cin >> t; while (t--){ solve(); } return 0; }

6|0G. 顾影自怜


我们可以枚举每一个数ai,作为第一个最大值出现。为了计算答案,我们要预处理L[i]表示i左侧第一个比ai大的数的下标,R[i]表示i右侧第一个比ai大的数的下标。lst[i]表示i第一个ai出现的下标,nxt[i]表示i后第kai出现的位置。

ai作为第一个最大值的合法左端点的范围是(min(lst[i],L[i]),i],右端点的范围是[nxt[i],R[i])

L[i],R[i]用单调栈统计,lst[i],nxt[i]用值域桶统计,总体复杂度O(N)

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui32 = unsigned int; #define int i64 using vi = vector<int>; void solve() { int n, k; cin >> n >> k; vi a(n + 1); for(int i = 1; i <= n; i ++) cin >> a[i]; for(int i = 1; i <= n; i ++) assert( 1 <= a[i] and a[i] <= n); vector vis(n + 1, vi(1, 0)); for(int i = 1;i <= n; i ++) vis[a[i]].push_back(i); vi lst(n + 1), nxt(n + 1, -1); for(int i = 1; i <= n; i ++) { if(vis[i].size() - 1 < k) continue; for(int l = 1, r = k; r < vis[i].size(); l ++, r ++) { lst[vis[i][l]] = vis[i][l - 1]; nxt[vis[i][l]] = vis[i][r]; } } vi L(n + 1); stack<int> stk; for(int i = 1; i <= n; i ++) { while(not stk.empty() and a[stk.top()] <= a[i]) stk.pop(); if(stk.empty()) L[i] = 0; else L[i] = stk.top(); stk.push(i); } vi R(n + 1); stk = stack<int>(); for(int i = n; i >= 1; i --) { while(not stk.empty() and a[stk.top()] <= a[i]) stk.pop(); if(stk.empty()) R[i] = n + 1; else R[i] = stk.top(); stk.push(i); } int res = 0; for(int i = 1; i <= n; i ++){ if(nxt[i] == -1) continue; int l = i - max(lst[i], L[i]); int r = R[i] - nxt[i]; if(l < 0 or r < 0) continue; res += l * r; } cout << res << "\n"; return ; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int T; cin >> T; while(T --) solve(); return 0; }

7|0J. 结课风云


签到

#include <bits/stdc++.h> using namespace std; using i64 = long long; using ui32 = unsigned int; using vi = vector<int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; int a, b, c; cin >> a >> b >> c; vi x(n), y(n); for(int i = 0 ; i < n; i ++) cin >> x[i] >> y[i]; int ret = 0; for(int i = 0; i < n; i ++) ret += (x[i] + y[i]) < c; int d; cin >> d; for(int i = 0; i < n; i ++) x[i] = min(x[i] + d, a); int res = 0; for(int i = 0; i < n; i ++) res += (x[i] + y[i]) < c; cout << ret - res; return 0; }

8|0L. 龙之研习


可以发现,不会有任何一个数同时满足两个及以上条件。因此就变成了简单的容斥。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui32 = unsigned int; #define int i64 using vi = vector<int>; int base = 0; vi p1, p2; void init() { p1.push_back(4), p2.push_back(100); while(p2.back() != 1e18) { p1.push_back(p1.back() * 100); p2.push_back(p2.back() * 100); } } int calc(int x) { int y = x; for(int i = 0; i < p1.size(); i ++) y = y - (x / p1[i]) + (x / p2[i]); return y; } void solve() { int k; cin >> k; int l = 1, r = 2e18, ret = -1; while(l <= r) { int mid = (l + r) / 2; int cnt = calc(mid); if(cnt - base >= k) ret = mid, r = mid - 1; else l = mid + 1; } cout << ret << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); init(); base = calc(2024); int T; cin >> T; while(T --) solve(); return 0; }

9|0M. 盲盒谜题


模拟题,这里把放和删操作做了一个封装。

有一个注意点是,只要被放了,最后就一定会拿到,因此可以在放的过程中直接统计拿了多少。

#include <bits/stdc++.h> using namespace std; using i64 = long long; using ui32 = unsigned int; using vi = vector<int>; using pii = pair<int,int>; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int have, m, k, lucky, used = 0; cin >> have >> m >> k >> lucky; vector<int> a(k + 1); for(int i = 1; i <= k; i ++) cin >> a[i]; bool ok = true; vi cnt(m + 1); // 统计个数 vector g(3, vi(3, -1)); // 记录图 vector<pii> pos = {{1,1}, {0,0}, {0,1}, {0,2}, {1,0}, {1,2}, {2,0}, {2,1}, {2,2}}; vector<array<int,3>> step3_line = { {0, 1, 8}, {0, 2, 7}, {0, 3, 6}, {0, 4, 5}, {1, 2, 3}, {1, 4, 6}, {3, 5, 8}, {6, 7, 8}}; auto solve = [&]() -> void { bool opted = false, delSpecial = false; auto val = [&](int i) -> int{ const auto &[x, y] = pos[i]; return g[x][y]; }; auto add = [&](int i) -> void { const auto &[x, y] = pos[i]; opted = true; have --; used ++; cnt[a[used]] ++; g[x][y] = a[used]; if(a[used] == 0) { have ++; g[x][y] = -1; } else if(a[used] == lucky) { have ++; } return; }; auto del = [&](int i, bool special = false) -> void { if(i == 0 and special == false) { delSpecial = true; return; } const auto &[x, y] = pos[i]; opted = true; g[x][y] = -1; return; }; // step 1 for(int i = 0; i < 9; i ++) while(val(i) == -1 and have > 0 and used < k) add(i); // step 2 set<int> cntStep2; for(auto [x, y] : pos) cntStep2.insert(g[x][y]); if(cntStep2.size() == 9 and cntStep2.count(-1) == 0){ del(0, true); return; } // step 3 for(const auto &[x, y, z] : step3_line) { if(val(x) == -1) continue; if(val(x) != val(y) or val(x) != val(z)) continue; del(x), del(y), del(z); have += 5; // 奖励 } // step 4 for(int i = 0; i < 9; i ++ ) { if(val(i) == -1) continue; for(int j = i + 1; j < 9 and val(i) != -1 ; j ++) { if(val(i) != val(j)) continue; del(i), del(j); have ++; } } // step 5 del(0, delSpecial); // step 6 if(opted == false){ ok = false; return; } set<int> cntStep6; for(auto [x, y] : pos) cntStep6.insert(g[x][y]); if(cntStep6.size() == 1 and *cntStep6.begin() == -1) have += 10; return; }; while(ok) solve(); for(auto i : cnt) cout << i << " "; cout << "\n"; if(have > 0) cout << "Unhappy! " << have << "\n"; return 0; }

__EOF__

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