河南萌新联赛2024第(五)场:信息工程大学
河南萌新联赛2024第(五)场:信息工程大学
前言
有点水这场,原题和板子貌似有点多。。
A-日历游戏_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
首先不看年份的话,显然 \(8/1\) 败,\(7/31\) 胜,\(7/30\) 败,\(7/29\) 胜,\(\dots\),以此类推,就能发现一个 \((m+d)\bmod 2=0\) \((m为月,d为日)\) 时,必胜,\((m+d)\bmod 2=1\) 时必败的规律,但是要注意有两个特殊日期,就是 \(9/30\) 和 \(11/30\),\(9/30\rightarrow 10/1\ or\ 10/30,11/30\rightarrow 12/1\ or \ 12/30\),可以控制下一次的奇偶性,在最优策略下可以控制必胜。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { int x, y, z; cin >> x >> y >> z; if ((y == 9 && z == 30) || (y == 11 && z == 30) || (y + z) % 2 == 0) cout << "YES\n"; else cout << "NO\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
B-学生分组_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
首先就是特判下平均数在不在 \([L,R]\) 的区间内。
然后就是去比较下所有数小于 \(L\) 和大于 \(R\) 的部分哪部分最大即可,最大的补在另一边,剩下补平均数即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; i64 sum = 0; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; sum += a[i]; } i64 l, r; cin >> l >> r; if (sum / n < l || (sum + n - 1) / n > r) { cout << "-1\n"; return 0; } i64 x = 0, y = 0; for (int i = 1; i <= n; i ++) { if (a[i] < l) x += l - a[i]; else if (a[i] > r) y += a[i] - r; } cout << max(x, y) << '\n'; return 0; }
C-小美想收集_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
种类(扩展域)并查集的模板。
贪心的按冲突值从大到小排序,然后用并查集维护两个集合,以 \(x\) 和 \(x+n\) 代表其自身的集合和它相对的集合,假设 \(a,b\) 冲突,那我们就把 \(a,b+n\) 连起来代表放一个集合里,\(b,a+n\) 放一个集合。
当枚举到的 \(a,b\) 如果在之前的分配中被分到一个集合了,那么此时它们的冲突值即是最大的,输出即可。
二分 + 二分图染色也可以写,具体的可以去看看P1525 [NOIP2010 提高组] 关押罪犯 这道题的题解。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; struct UFS { int sz; vector<int> rank, p; void link(int x, int y) { if (x == y) return; if (rank[x] > rank[y]) p[y] = x; else p[x] = y; if (rank[x] == rank[y]) rank[y]++; } void init(int n) { sz = n; rank.resize(n + 1); p.resize(n + 1); for (int i = 0; i <= sz; i++) { p[i] = i; rank[i] = 0; } } int find(int x) { return x == p[x] ? x : (p[x] = find(p[x])); } void unin(int x, int y) { link(find(x), find(y)); } void compress() { for (int i = 0; i <= sz; i++) find(i); } }; //种类并查集 merge(y + n, x),merge(x + n, y) int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<tuple<i64, int, int>> g; for (int i = 0; i < m; i ++) { i64 u, v, w; cin >> u >> v >> w; g.push_back({w, u, v}); } sort(g.begin(), g.end(), greater<>()); UFS ufs; ufs.init(2 * n); i64 ans = 0; for (int i = 0; i < m; i ++) { auto [w, u, v] = g[i]; if (ufs.find(u) == ufs.find(v) || ufs.find(u + n) == ufs.find(v + n)) { ans = w; break; } ufs.unin(u + n, v); ufs.unin(v + n, u); } cout << ans << '\n'; return 0; }
D-区间问题1_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
普通线段树板题,树状数组差分也可以。
据说直接 \(O(qn)\) 差分都有人过了
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; template<class Node> struct SegmentTree { #define lc u<<1 #define rc u<<1|1 const int n, N; vector<Node> tr; SegmentTree(): n(0) {} SegmentTree(int n_): n(n_), N(n * 4 + 10) { tr.reserve(N); tr.resize(N); } SegmentTree(vector<int> init) : SegmentTree(init.size()) { function<void(int, int, int)> build = [&](int u, int l, int r) { tr[u].l = l, tr[u].r = r; init_lazy(tr[u]); if (l == r) { tr[u] = {l, r, 0, init[l]}; return ; } i64 mid = (l + r) >> 1; build(lc, l, mid); build(rc, mid + 1, r); pushup(tr[u], tr[lc], tr[rc]); }; build(1, 1, n); } void cal_lazy(Node & fa, Node & ch) { i64 b = fa.add; ch.sum += b; } void tag_union(Node& fa, Node& ch) { i64 b = fa.add; ch.add += b; } void init_lazy(Node& u) { u.add = 0; } void pushdown(i64 u) { if (tr[u].add != 0) { cal_lazy(tr[u], tr[lc]); cal_lazy(tr[u], tr[rc]); tag_union(tr[u], tr[lc]); tag_union(tr[u], tr[rc]); init_lazy(tr[u]); } } void pushup(Node& U, Node& L, Node& R) { //上传 U.sum = L.sum + R.sum; } void modify(int u, int l, int r, int k) { if (tr[u].l >= l && tr[u].r <= r) { tr[u].add += k; tr[u].sum += k; return ; } pushdown(u); int mid = (tr[u].l + tr[u].r) >> 1; if (l <= mid) modify(lc, l, r, k); if (r > mid) modify(rc, l, r, k); pushup(tr[u], tr[lc], tr[rc]); } Node query(int u, int l, int r) { //区查 if (l <= tr[u].l && tr[u].r <= r) return tr[u]; i64 mid = tr[u].l + tr[u].r >> 1; pushdown(u); i64 res = LLONG_MIN >> 1; if (r <= mid) return query(lc, l, r); if (l > mid) return query(rc, l, r); Node U; Node L = query(lc, l, r), R = query(rc, l, r); pushup(U, L, R); return U; } }; struct Node { //线段树定义 i64 l, r, add, sum; }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; } SegmentTree<Node> tr(a); int q; cin >> q; while (q--) { int op; cin >> op; if (op == 1) { int l, r, d; cin >> l >> r >> d; tr.modify(1, l, r, d); } else { int x; cin >> x; auto ans = tr.query(1, x, x); cout << ans.sum << '\n'; } } return 0; }
E-哥德巴赫猜想_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
先筛出 \(5e4\) 以内的质数,然后枚举两个数,用 set 维护第三个数判断一下即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; //欧拉函数,质数 vector<int> euler_range(int n) { vector<int> phi(n + 1), prime; vector<bool> is_prime(n + 1, true); is_prime[1] = 0, phi[1] = 1; for (int i = 2; i <= n; i++) { if (is_prime[i]) prime.push_back(i), phi[i] = i - 1; for (int j = 0; j < (int)prime.size() && i * prime[j] <= n; j++) { is_prime[i * prime[j]] = 0; if (i % prime[j]) phi[i * prime[j]] = phi[i] * (prime[j] - 1); else { phi[i * prime[j]] = phi[i] * prime[j]; break; } } } return prime; } constexpr int N = 5e4 + 10, M = N - 5; auto pr = euler_range(N); set<int> s(pr.begin(), pr.end()); void solve() { int n; cin >> n; for (auto &i : pr) { for (auto &j : pr) { if (i + j >= n) break; if (s.count(n - i - j)) { cout << i << ' ' << j << ' ' << n - i - j << '\n'; return ; } } } cout << "-1\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
F-小美想跑步_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
把样例画个图可以发现,其实就是让你在有向图中找起到到其他点的最短距离,和其他点到起点的最短距离,正向存边跑 dijkstra 就是起点到到其他点的距离,反向存边跑 dijkstra 就是其他点到起点最短距离。
所以正反跑两遍 dijkstra 即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; struct DIJ { using i64 = long long; using PII = pair<i64, i64>; vector<i64> dis; vector<vector<PII>> G; DIJ() {} DIJ(int n) { dis.assign(n + 1, 1e18); G.resize(n + 1); } void add(int u, int v, int w) { G[u].emplace_back(v, w); } void dijkstra(int s) { priority_queue<PII> que; dis[s] = 0; que.push({0, s}); while (!que.empty()) { auto p = que.top(); que.pop(); int u = p.second; if (dis[u] < -p.first) continue; for (auto [v, w] : G[u]) { if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; que.push({ -dis[v], v}); } } } } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; DIJ dij1(n), dij2(n); for (int i = 0; i < m; i ++) { int u, v, w; cin >> u >> v >> w; dij1.add(u, v, w); dij2.add(v, u, w); } dij1.dijkstra(1); dij2.dijkstra(1); i64 ans = 0; for (int i = 2; i <= n; i ++) { ans += dij1.dis[i] + dij2.dis[i]; } cout << ans << '\n'; return 0; }
G-爬楼梯_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
基础动态规划,经典爬楼梯问题。
设 \(f_i\) 表示爬到第 \(i\) 层的方案数。
代码
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<Z> dp(n + 10, 0); dp[1] = 1, dp[2] = 2, dp[3] = 4; for (int i = 4; i <= n; i ++) { dp[i] += dp[i - 1] + dp[i - 2] + dp[i - 3]; } cout << dp[n] << '\n'; return 0; }
H-区间问题2_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
卡常说实话有点逆天了。
貌似只有快读+ST表可以过,ST表还不能是封装的。
反正我线段树被卡成狗了
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; const int maxn = 1e6 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while (c < '0' || c > '9') {if (c == '-')f = -1; c = getchar();} while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();} return x * f; } int Max[maxn][21]; int main() { int n = read(); for (int i = 1; i <= n; i++) Max[i][0] = read(); for (int j = 1; j <= 20; j++) for (int i = 1; i + (1 << j) - 1 <= n; ++i) Max[i][j] = max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]); int l, r; int m = read(); for (int i = 1; i <= m; ++i) { scanf("%d %d", &l, &r); int renk = log2(r - l + 1); int temp = max(Max[l][renk], Max[r - (1 << renk) + 1][renk]); printf("%d\n", temp); } return 0; }
I-小美想打音游_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
就是选择一个 \(a\),使得所有数到它的绝对值距离最小,有这样一个定理:
将 a 的所有元素变为 a 的中位数是最优的。
貌似是叫中位数贪心,证明网上应该都能搜到。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i ++) { cin >> a[i]; } sort(a.begin() + 1, a.end()); i64 avg = a[(n + 1) / 2]; i64 ans = 1; for (int i = 1; i <= n; i ++) { ans += abs(a[i] - avg); } cout << ans << '\n'; return 0; }
J-平方根_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
签到。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; void solve() { i64 n; cin >> n; cout << (i64)sqrt(n) << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
K-小美想游泳_河南萌新联赛2024第(五)场:信息工程大学 (nowcoder.com)
思路
用堆优化的 dijkstra 在转移 \(dis\) 数组的时候将其用来维护路径最大值即可。
代码
#include <bits/stdc++.h> using namespace std; using i64 = long long; struct DIJ { using i64 = long long; using PII = pair<i64, i64>; vector<i64> dis; vector<vector<PII>> G; DIJ() {} DIJ(int n) { dis.assign(n + 1, 1e18); G.resize(n + 1); } void add(int u, int v, int w) { G[u].emplace_back(v, w); } void dijkstra(int s) { priority_queue<PII> que; dis[s] = 0; que.push({0, s}); while (!que.empty()) { auto p = que.top(); que.pop(); int u = p.second; if (dis[u] < -p.first) continue; for (auto [v, w] : G[u]) { if (dis[v] > max(dis[u], w)) { dis[v] = max(dis[u], w); que.push({ -dis[v], v}); } } } } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; DIJ dij(n); for (int i = 0; i < m; i ++) { int u, v, w; cin >> u >> v >> w; dij.add(u, v, w); dij.add(v, u, w); } int s, t; cin >> s >> t; dij.dijkstra(s); cout << dij.dis[t] << '\n'; return 0; }
本文作者:Ke_scholar
本文链接:https://www.cnblogs.com/Kescholar/p/18359631
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2023-08-14 AtCoder Beginner Contest 314
2023-08-14 牛客周赛 Round 7