------------恢复内容开始------------c++
为了方便(节约时间), 因此题面就不放到博客里面了, 就直接链接放过去了spa
模拟赛传送门.net
T1 - 树的直径
T2 - 积木
T3 - 软件公司
T4 - 我图呢code
因为代码和帮别人修题的缘故, 因此有一道题就没改好, 因此就不放代码了ip
T1 就是标准的 LCA。
能够边输入处理父节点和深度, 再处理阶乘就能够了get
void dfs (int u, int fa) { p[u][0] = fa; for (reg int i = 1; (1 << i) <= hhd[u].deep; ++ i) p[u][i] = p[p[u][i - 1]][i - 1]; } int lca (int a, int b) { if (hhd[a].deep > hhd[a].deep) swap (a, b); for (reg int i = 20; i >= 0; -- i) if (hhd[a].deep <= hhd[b].deep - (1 << i)) b = p[b][i]; if(a == b) return a; for (reg int i = 20; i >= 0; -- i) { if (p[a][i] == p[b][i]) continue; else { a = p[a][i]; b = p[b][i]; } } return p[a][0]; } int main () { scanf ("%d", &m); for (reg int i = 1; i <= 4; ++ i) { hhd[i].deep = 1; hhd[i].y = 1; dfs (i, 1); } hhd[1].y = 0; hhd[1].deep = 0;
不是很难, 跳过博客
二分答案, 以一个三重循环的 DP 做为 check 来二分。it
对于 \(f_{i,j}\) 表示前 \(i\) 我的 作了 \(j\) 项一个项目的子项目的状况下能作的最多项二项目的子项目
而后咱们考虑从 \(f_{i-1, j-k}\) 来转移状态, 以使二项目完成的子项目最多, 同时使一项目完成的子项目符合 \(j\) 的大小io
#include <bits/stdc++.h> #define N 105 using namespace std; int n, m; int x[N], y[N], f[N][N]; int main () { freopen ("company.in", "r", stdin); freopen ("company.out", "w", stdout); scanf ("%d%d", &n, &m); for (int i = 1; i <= n; ++ i) scanf ("%d%d", &x[i], &y[i]); int l = 0, r = N - 5; while (l < r) { int mid = (l + r) / 2; memset (f, -0x3f3f3f, sizeof (f)); f[0][0] = 0; for (int i = 1; i <= n; ++ i) for (int j = 0; j <= m; ++ j) for (int k = 0; k <= j; ++ k) if (mid - k * x[i] < 0) break; else f[i][j] = max (f[i][j], f[i - 1][j - k] + (mid - k * x[i]) / y[i]); if (f[n][m] >= m) r = mid; else l = mid + 1; } printf ("%d", l); return 0; }
太过毒瘤, 没改好, 不太好解析class