2024 Xiangtan University Summer Camp-Div.2

1|0A. 二度树上的染色游戏


因为题目保证了是二叉树,所以每次至多只需要选择一个子节点染成红色。所以可以贪心的选择红色权值小的子树即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; const i32 inf = INT_MAX / 2; const i64 INF = LLONG_MAX / 2; #define int i64 using vi = vector<int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; vi a(n + 1); int sum = 0; for (int i = 1; i <= n; i++) cin >> a[i], sum += a[i]; vector<vi> e(n + 1); for (int i = 1, u, v; i < n; i++) { cin >> u >> v; e[u].push_back(v), e[v].push_back(u); } auto dfs = [&](auto &&self, int x, int fa) -> int { int cnt = 0; for (int y: e[x]) cnt += y != fa; if (cnt < 2) return a[x]; int ans = inf; for (int y: e[x]) { if (y == fa) continue; ans = min(ans, self(self, y, x)); } return ans + a[x]; }; int red = dfs(dfs, 1, -1); cout << sum - red - red; return 0; }

2|0B. 小文的排列


我们可以把序列分层若干个子段,这样的话,除了开头的子段和结尾的子段,剩下的字段必须都是完整的m的排列,并且开头和结尾必须是m排列的子段。

因此我们可以用双指针扫描出所有的合法子段,然后做一个简单的dp 就好了。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; const i32 inf = INT_MAX / 2; const i64 INF = LLONG_MAX / 2; #define int i64 using vi = vector<int>; using pii = pair<int, int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m; cin >> n >> m; vi a(n + 1); for (int i = 1; i <= n; i++) cin >> a[i]; if (ranges::max(a) > m) { cout << "NO\n"; return 0; } vector<vi> e(n + 1); set<int> vis; for (int l = 1, r = 0; l <= n; l++) { while (r + 1 <= n and vis.count(a[r + 1]) == 0) { r++, vis.insert(a[r]); if (l == 1) e[r].push_back(1); } if (r == n or vis.size() == m) e[r].push_back(l); vis.erase(a[l]); } vi f(n + 1); f[0] = 1; for (int r = 1; r <= n; r++) for (int l: e[r]) if (f[l - 1]) { f[r] = 1; break; } if (f[n]) cout << "YES"; else cout << "NO"; return 0; }

3|0C. gcd hard version


区间最大公约数可以用ST表求,区间和可以用前缀和求。

对于当前的区间[l,r],如果r变大,最大公约数是不增的,区间和是不减的,因此如果[l,r]满足,[l,r+1]一定满足。

所以我们可以枚举左端点,然后直接二分出右端点。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; const i32 inf = INT_MAX / 2; const i64 INF = LLONG_MAX / 2; #define int i64 using vi = vector<int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; int lg2N = log2(n); vi lg2(n + 1); vector f(n + 1, vi(lg2N + 1)); lg2[0] = -1; for (int i = 1; i <= n; i++) { cin >> f[i][0]; lg2[i] = lg2[i / 2] + 1; } for (int j = 1; j <= lg2N; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) f[i][j] = gcd(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); auto query = [=](int l, int r) { assert(l <= r); int s = lg2[r - l + 1]; return gcd(f[l][s], f[r - (1 << s) + 1][s]); }; vi pre(n + 1); for (int i = 1; i <= n; i++) { cin >> pre[i]; pre[i] += pre[i - 1]; } int res = 0; for (int i = 1; i <= n; i++) { int l = i, r = n, ans = -1; while (l <= r) { int mid = (l + r) / 2; if (query(i, mid) <= pre[mid] - pre[i - 1]) ans = mid, r = mid - 1; else l = mid + 1; } if (ans == -1) continue; res += n - ans + 1; } cout << res; return 0; }

4|0D. 战至终章


挑战的顺序一定是一种拓扑序。有多个可以挑战的情况下挑战a最小的一定最优。因此我们在求拓扑序的时候使用优先队列即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ldb = long double; const i32 inf = INT_MAX / 2; const i64 INF = LLONG_MAX / 2; #define int i64 using vi = vector<int>; using pii = pair<int, int>; i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, p; cin >> n >> p; vi a(n + 1), b(n + 1), deg(n + 1); vector<vi> e(n + 1); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) cin >> b[i]; priority_queue<pii> heap; for (int i = 1; i <= n; i++) { cin >> deg[i]; if (deg[i] == 0) heap.emplace(-a[i], i); for (int j = 0, x; j < deg[i]; j++) cin >> x, e[x].push_back(i); } vi res; while (not heap.empty()) { auto [_, x] = heap.top(); heap.pop(); if (a[x] > p) continue; res.push_back(x), p += b[x]; for (auto y: e[x]) if (--deg[y] == 0) { heap.emplace(-a[y], y); } } ranges::sort(res); cout << res.size() << "\n"; for (auto i: res) cout << i << " "; return 0; }

__EOF__

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