A. Humidifier 1
模拟
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int n; cin >> n; int pre = 0, water = 0; rep(i, n) { int t, v; cin >> t >> v; water -= t-pre; water = max(water, 0); water += v; pre = t; } cout << water << '\n'; return 0; }
B. Humidifier 2
模拟
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; int main() { int h, w, d; cin >> h >> w >> d; vector<string> s(h); rep(i, h) cin >> s[i]; int ans = 0; rep(i1, h)rep(j1, w) { if (s[i1][j1] == '#') continue; rep(i2, h)rep(j2, w) { if (s[i2][j2] == '#') continue; if (i1 == i2 and j1 == j2) continue; int cnt = 0; rep(i, h)rep(j, w) { if (s[i][j] == '#') continue; bool humid = false; if (abs(i-i1)+abs(j-j1) <= d) humid = true; if (abs(i-i2)+abs(j-j2) <= d) humid = true; if (humid) cnt++; } ans = max(ans, cnt); } } cout << ans << '\n'; return 0; }
C. Humidifier 3
以加湿器为源点跑多源bfs
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using P = pair<int, int>; const int di[] = {-1, 0, 1, 0}; const int dj[] = {0, 1, 0, -1}; int main() { int h, w, d; cin >> h >> w >> d; vector<string> s(h); rep(i, h) cin >> s[i]; const int INF = 1001001001; vector dist(h, vector<int>(w, INF)); queue<P> q; rep(i, h)rep(j, w) { if (s[i][j] == 'H') { dist[i][j] = 0; q.emplace(i, j); } } while (q.size()) { auto [i, j] = q.front(); q.pop(); rep(v, 4) { int ni = i+di[v], nj = j+dj[v]; if (ni < 0 or nj < 0 or ni >= h or nj >= w) continue; if (s[ni][nj] == '#') continue; if (dist[ni][nj] != INF) continue; dist[ni][nj] = dist[i][j]+1; q.emplace(ni, nj); } } int ans = 0; rep(i, h)rep(j, w) if (dist[i][j] <= d) ans++; cout << ans << '\n'; return 0; }
D. 9 Divisors
不难发现只有可分解成 和 形式的数才是合法数
可以先筛出 以内的所有素数
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; struct Sieve { int n; vector<int> f, primes; Sieve(int n=1): n(n), f(n+1) { f[0] = f[1] = -1; for (ll i = 2; i <= n; ++i) { if (f[i]) continue; primes.push_back(i); f[i] = i; for (ll j = i*i; j <= n; j += i) { if (!f[j]) f[j] = i; } } } bool isPrime(int x) { return f[x] == x; } }; int main() { ll n; cin >> n; Sieve sieve(1e6); auto primes = sieve.primes; int ans = 0; for (int p1 : primes) { for (int p2 : primes) { if (p2 >= p1) break; if ((ll)p1*p1*p2*p2 > n) break; ans++; } } for (int p : primes) { ll x = 1; rep(i, 8) x *= p; if (x > n) break; ans++; } cout << ans << '\n'; return 0; }
E. Sum of Max Matching
可以考虑用Kruskal跑MST的过程
假设当前要合并边 ,且这条边对应的边权为 ,不难发现以这条边的边权为最大值的路径数为点 所在连通分量中 点的数量和点 所在连通分量中 点的数量之间取最小值,或者,点 也可以在点 所在的连通分量中,点 也可以在点 所在连通分量中
注意:在一个连通分量里不可能同时有 和 (因为可以直接用掉)
代码实现
#include <bits/stdc++.h> #include <atcoder/all> using namespace atcoder; #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; int main() { int n, m, k; cin >> n >> m >> k; vector<tuple<int, int, int>> es; rep(i, m) { int a, b, c; cin >> a >> b >> c; --a; --b; es.emplace_back(c, a, b); } ranges::sort(es); vector<int> A(n), B(n); rep(i, k) { int a; cin >> a; --a; A[a]++; } rep(i, k) { int b; cin >> b; --b; B[b]++; } ll ans = 0; dsu uf(n); for (auto [c, u, v] : es) { if (uf.same(u, v)) continue; u = uf.leader(u); v = uf.leader(v); if (A[v]) swap(u, v); if (A[u] and B[v]) { int x = min(A[u], B[v]); ans += (ll)c*x; A[u] -= x; B[v] -= x; } int sumA = A[u]+A[v]; int sumB = B[u]+B[v]; uf.merge(u, v); A[uf.leader(u)] = sumA; B[uf.leader(u)] = sumB; } cout << ans << '\n'; return 0; }
F. Diversity
先将所有物品按颜色 排序
记 dp[i][j][0/1]
表示到第 个物品为止选了若干物品且一定选第 个物品最多花费 元且当前是否增加了颜色种类数时的最大满意度
代码实现
#include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (n); ++i) using namespace std; using ll = long long; inline void chmax(ll& x, ll y) { if (x < y) x = y; } int main() { int n, x, K; cin >> n >> x >> K; vector<tuple<int, int, int>> items; rep(i, n) { int p, u, c; cin >> p >> u >> c; items.emplace_back(c, p, u); } ranges::sort(items); vector dp(x+1, vector<ll>(2)); int pre_c = -1; for (auto [c, p, u] : items) { if (pre_c != c) { rep(i, x+1) chmax(dp[i][0], dp[i][1]); pre_c = c; } vector old(x+1, vector<ll>(2)); swap(dp, old); rep(i, x+1) { rep(j, 2) chmax(dp[i][j], old[i][j]); int ni = i+p; if (ni <= x) { chmax(dp[ni][1], old[i][1]+u); chmax(dp[ni][1], old[i][0]+u+K); } } } ll ans = dp[x][1]; cout << ans << '\n'; return 0; }
G. Bar Cover
最好想的方式是直接线段树+凸包闵可夫斯基和。
具体的,每个节点维护 dp[a][b][x]
表示取的最左的数离 为 ,最右的数距离 为 ,选择了 个数的最大权值。不难发现 dp[a][b][x]
是关于 上凸的。合并左右儿子信息就需要求闵可夫斯基和,直接归并就好了。
分析一下复杂度,应该是 的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】