牛客小白月赛88

1|0A-超级闪光牛可乐


#include <bits/stdc++.h> using namespace std; using f64 = double_t; using i32 = int32_t; using i64 = int64_t; using u64 = uint64_t; #define int long long i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int x, n; cin >> x >> n; char c, t; int y = -1; for (int i = 1, v; i <= n; i++) { cin >> c >> v; if (v > y) y = v, t = c; } cerr << y << "\n"; y = ( x + y - 1 ) / y ; cerr << y << "\n"; if( y > 1000 ){ cout << "-1\n"; }else{ while( y -- ) cout << t; cout << "\n"; } return 0; }

2|0B-人列计算机


#include <bits/stdc++.h> using namespace std; using f64 = double_t; using i32 = int32_t; using i64 = int64_t; using u64 = uint64_t; #define int long long i32 main() { cin.tie(nullptr)->sync_with_stdio(false); vector<string> s(5); for (auto &it: s) getline(cin, it); int f = 0; for (auto i: s[2]) { if (i == '&') f = 1; else if (i == 'O') f = 2; } if (f == 1) { int x = s[1].front() == '1'; int y = s[3].front() == '1'; cout << (x & y) << "\n"; } else if (f == 2) { int x = s[2].front() == '1'; cout << (!x) << "\n"; } else { int x = s[1].front() == '1'; int y = s[3].front() == '1'; cout << (x | y) << "\n"; } return 0; }

3|0C-时间管理大师


#include <bits/stdc++.h> using namespace std; using f64 = double_t; using i32 = int32_t; using i64 = int64_t; using u64 = uint64_t; #define int long long i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int n; cin >> n; set<int> cnt; for (int i = 1, h, m; i <= n; i++) { cin >> h >> m; m += h * 60; cnt.insert(m - 1); cnt.insert(m - 3); cnt.insert(m - 5); } cout << cnt.size() << "\n"; for( auto i : cnt ){ cout << i / 60 << " " << i % 60 << "\n"; } return 0; }

4|0D-我不是大富翁


二维 dp,下标为了方便可以直接转换成[0,n1]

#include <bits/stdc++.h> using namespace std; using f64 = double_t; using i32 = int32_t; using i64 = int64_t; using u64 = uint64_t; #define int long long i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int n, m; cin >> n >> m; vector<i32> f(n); f[0] = true; for (int i = 1, x; i <= m; i++) { cin >> x, x %= n; vector<i32> g(n); for (int j = 0; j < n; j++) { if (f[j] == false) continue; g[(j + x) % n] |= f[j]; g[(j - x + n) % n] |= f[j]; } f.swap(g); } if (f[0]) cout << "YES\n"; else cout << "NO\n"; return 0; }

5|0E-多重映射


5|1反序递推


toi,j标准最后i个操作下j会被变成toi,j,显然to0,j=j

然后我们设倒数第i次操作是xi变为yi,则

toi,j={toi1,jjxitoi1,yij=xi

所以根据这个规律倒过来递推即可,可以优化一维空间。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; #define int long long using vi = vector<int>; using pii = pair<int, int>; void solve() { int n, m; cin >> n >> m; vector<i32> a(n); for (auto &i: a) cin >> i; vector<pair<i32, i32>> op(m); for (auto &[x, y]: op) cin >> x >> y; reverse(op.begin(), op.end()); map<i32, i32> to; for (auto &[x, y]: op) { if (to.count(y)) to[x] = to[y]; else to[x] = y; } for (auto i: a) { if (to.count(i)) cout << to[i] << " "; else cout << i << " "; } cout << "\n"; return; } i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int TC; cin >> TC; while (TC--) solve(); return 0; }

5|2启发式合并


dic[x]表示当前被变成x的集合,则一次操作M(x)=y等价于把dic[x]中的数字全部移动到dic[y]中。

然后,启发式合并就保证每次把较小集合插入到较大的集合中,因为在高版本的c++std::swapO(1)的。

当然可以通过指针数组来实现。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<int>; using pii = pair<int, int>; const i32 N = 1e6; vector<vi> dic(N + 1); void solve() { int n, m; cin >> n >> m; set<int> vis; for (int i = 0, x; i < n; i++) cin >> x, dic[x].push_back(i), vis.insert(x); for (int x, y; m; m--) { cin >> x >> y; if (x == y) continue; if (dic[x].size() > dic[y].size()) swap(dic[x], dic[y]); dic[y].insert(dic[y].end(), dic[x].begin(), dic[x].end()); dic[x].clear(); vis.insert(y), vis.erase(x); } vi res(n); for (const auto &i: vis) { for (const auto &pos: dic[i]) res[pos] = i; dic[i].clear(); } for (const auto &i: res) cout << i << " "; cout << "\n"; return; } i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int TC; cin >> TC; while (TC--) solve(); return 0; }

5|3记忆化搜索


我们可以把操作M(xi)=yi,看成一条有向边(xi,yi,i),则转化操作就变成了在图上每次走边权最小的边且所走的边权必须是一个递增的序列。

然后变换的过程就是沿着一条链走,且链上所经过的所有点最终都变成了链上的最后一个点。

所以计划ans[i]就表示了经过i边后最终会变成什么,这样可以保证每条边只走一次,复杂度就是O(N+M)

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<int>; using pii = pair<int, int>; const i32 N = 1e6; vector<vector<pii>> e(N + 1); vi ans(N + 1); int dfs(int x, int time) { if (e[x].empty() or e[x].back().second <= time) return x; int it = -1; for (int l = 0, r = e[x].size() - 1, mid; l <= r;) { mid = (l + r) / 2; if (e[x][mid].second > time) it = mid, r = mid - 1; else l = mid + 1; } assert(it != -1); auto &[y, newTime] = e[x][it]; if (ans[newTime] != -1) return ans[newTime]; return ans[newTime] = dfs(y, newTime); } void solve() { int n, m; cin >> n >> m; vi a(n); for (auto &i: a) cin >> i, e[i].clear(); vector<pii> op(m); for (auto &[x, y]: op) cin >> x >> y, e[x].clear(), e[y].clear(); for (int i = 0; i < m; i++) { auto &[x, y] = op[i]; e[x].emplace_back(y, i + 1); ans[i + 1] = -1; } for (auto i: a) cout << dfs(i, 0) << " "; cout << "\n"; return; } i32 main() { cin.tie(nullptr)->sync_with_stdio(false); int TC; cin >> TC; while (TC--) solve(); return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18157796.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示