当前位置: 首页 > news >正文

Atcoder Beginner Contest 416

打的很炸裂啊。

D

贪心一下,一个 \(a_i\) 如果不能吃 \(b_j\) 超过 \(m\) 的话分配给它最小的 \(b\)。否则越小的 \(a_i\) 应当分配越大的 \(b_j\),排序一下处理即可。

const int N = 300010;
int T, n, m;
int a[N], b[N];void solve() {n = read(), m = read();rep(i, 1, n) a[i] = read();rep(i, 1, n) b[i] = read();sort(a + 1, a + 1 + n); sort(b + 1, b + 1 + n);LL ans = 0;for (int i = 1, l = 1, r = n; i <= n; i ++) {if (a[i] + b[r] < m) ans += (a[i] + b[l]) % m, l ++;else ans += (a[i] + b[r]) % m, r --; }printf("%lld\n", ans);
}int main() {T = read();while (T --) solve();return 0;
}

E

和官解不一样,感觉没啥技术,就是代码挺长。

显然 \(\Theta(QN^2)\) 能过,所以考虑 floyd。

加一条边 \((a, b, c)\),就 f[i][j] = min(f[i][j], f[i][a] + c + f[b][j]) 更新一下即可(注意这里是双向边,另一种情况也要更新)。

如果一个点变成了机场,那相当于直接连了 \(K\) 条边,直接更新会超时。

但你注意到这里所有边都类似于 f[i][u] + c + f[x][j],其中 f[x][j] 是固定的,所以只要预处理一下 f[i][u] 的最小值来更新即可。

const int N = 510;
int n, m, k, T, q, d[N];
int g[N][N], minv[N], minv2[N];signed main() {n = read(), m = read();for (int i = 0; i <= n; i ++)for (int j = 0; j <= n; j ++) g[i][j] = 1e18;while (m --) {int a = read(), b = read(), c = read();g[a][b] = min(g[a][b], c);g[b][a] = min(g[b][a], c);}k = read(), T = read();for (int i = 1; i <= k; i ++) d[i] = read();for (int i = 1; i <= k; i ++)for (int j = i + 1; j <= k; j ++)g[d[i]][d[j]] = min(g[d[i]][d[j]], T), g[d[j]][d[i]] = min(g[d[j]][d[i]], T); for (int i = 1; i <= n; i ++) g[i][i] = 0;for (int k = 1; k <= n; k ++)for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++)g[i][j] = min(g[i][j], g[i][k] + g[k][j]);for (int i = 1; i <= n; i ++) {minv[i] = minv2[i] = 1e18;for (int j = 1; j <= k; j ++) minv[i] = min(minv[i], g[i][d[j]]), minv2[i] = min(minv2[i], g[d[j]][i]);}int q = read();while (q --) {int op = read();if (op == 1) {int a = read(), b = read(), c = read();g[a][b] = min(g[a][b], c); g[b][a] = min(g[b][a], c);for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++) {g[i][j] = min(g[i][j], g[i][a] + c + g[b][j]);g[i][j] = min(g[i][j], g[i][b] + c + g[a][j]);}for (int i = 1; i <= n; i ++) {minv[i] = minv2[i] = 1e18;for (int j = 1; j <= k; j ++) minv[i] = min(minv[i], g[i][d[j]]), minv2[i] = min(minv2[i], g[d[j]][i]);}} else if (op == 2) {int x = read();for (int i = 1; i <= k; i ++) {g[d[i]][x] = min(g[d[i]][x], T), g[x][d[i]] = min(g[x][d[i]], T);minv[d[i]] = min(minv[d[i]], T), minv[x] = min(minv[x], T);}d[++ k] = x;for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++) {g[i][j] = min(g[i][j], minv[i] + T + g[x][j]);g[i][j] = min(g[i][j], g[i][x] + T + minv2[j]);}for (int i = 1; i <= n; i ++) {minv[i] = minv2[i] = 1e18;for (int j = 1; j <= k; j ++) minv[i] = min(minv[i], g[i][d[j]]), minv2[i] = min(minv2[i], g[d[j]][i]);}} else {int ans = 0;for (int i = 1; i <= n; i ++)for (int j = 1; j <= n; j ++)ans += g[i][j] > 1e17 ? 0 : g[i][j];printf("%lld\n", ans);}}return 0;
}

F

想是比较好想,但写对挺难的。

显然树形背包,设 \(f_{u, i, 0/1/2}\) 分别表示 \(u\) 子树内选 \(i\) 条路径,其中 \(u\) 不在路径上/是路径的端点/是路径的中间点。

转移有点魔怔可以看代码。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for (int i = (a); i <= (b); i ++)
#define fro(i, a, b) for (int i = (a); i >= b; i --)
#define INF 0x3f3f3f3f
#define eps 1e-6
#define lowbit(x) (x & (-x))
#define reg register
#define IL inline
typedef long long LL;
typedef std::pair<int, int> PII;
inline int read() {int x = 0, f = 1;char ch = getchar();while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }return x * f;
}const int N = 200010, M = 6;
int n, k, a[N];
vector<int> G[N];
int f[N][M][3], g[M][3];void dfs(int u, int fa) {f[u][1][1] = a[u]; f[u][0][0] = 0;for (auto v : G[u]) if (v != fa) {dfs(v, u); for (int i = 0; i <= k; i ++) for (int s = 0; s < 3; s ++) g[i][s] = -1e18;for (int i = 0; i <= k; i ++)for (int j = 0; i + j - 1 <= k; j ++) { // 小细节,如果 i + j 就错了if (i + j - 1 <= k && i + j - 1 >= 0) g[i + j - 1][2] = max(g[i + j - 1][2], f[u][i][1] + f[v][j][1]);if (i + j > k) continue;g[i + j][0] = max(g[i + j][0], f[u][i][0] + max({f[v][j][0], f[v][j][1], f[v][j][2]}));g[i + j][1] = max(g[i + j][1], f[u][i][0] + f[v][j][1] + a[u]);rep(t, 0, 2) g[i + j][1] = max(g[i + j][1], f[u][i][1] + f[v][j][t]);rep(t, 0, 2) g[i + j][2] = max(g[i + j][2], f[u][i][2] + f[v][j][t]);}   for (int i = 0; i <= k; i ++)for (int s = 0; s < 3; s ++) f[u][i][s] = max(f[u][i][s], g[i][s]);}
}signed main() {memset(f, -0x3f, sizeof f);n = read(), k = read();rep(i, 1, n) a[i] = read();for (int i = 1; i < n; i ++) {int a = read(), b = read();G[a].push_back(b), G[b].push_back(a);}dfs(1, 0); int ans = 0;for (int i = 0; i <= k; i ++)for (int j = 0; j < 3; j ++)ans = max(ans, f[1][i][j]);printf("%lld\n", ans);return 0;
}

G

http://www.njgz.com.cn/news/688.html

相关文章:

  • NCS添加.c.h文件
  • 明月直入,无心可猜
  • realtek网卡r8168如何强制设置1000M
  • mobaXterm免费版保存密码查询
  • 公司类型英文缩写
  • CVE-2020-17526 Apache Airflow 身份验证绕过漏洞 (复现)
  • Pwn2Own柏林2025次日战报:单日狂揽43.5万美元奖金,20个零日漏洞曝光
  • Day27
  • 猫树
  • 大道至简读后感
  • 一些感覺比較好的題目
  • 7.17XYD模拟赛
  • 如何把整套网站的源代码弄下来.250408
  • 牛客 周赛101 20250726
  • 人生的意义,就是没有意义.250421
  • 牛客2025多校 R3
  • 数论基础H
  • 推理大模型 vs 普通大模型:核心差异与国产代表产品
  • 【动态规划】树上连通块计数
  • Windows自带神器Robocopy一键备份文件文件夹,断点续传+多线程效率翻倍!.250429
  • 7月27日
  • 第八周作业
  • ASP.NET Core MVC 文件上传、文件扩展验证注解实现、文件扩展验证
  • 政治学和行政学属于法学
  • 基于RK3399嵌入式Linux驱动开发课程
  • Java日志框架
  • ASP.NET Core MVC 使用 EF Core 实现字段自动填充(如:添加时间 CreatedTime、更新时间 UpdatedTime)
  • 山西大同旅游攻略
  • 7月27日总结
  • 线性回归算法