26 Sep

28

P6927

由于 \(a<b\) 和 \(a>b\) 对内存大小的影响不同(增加 / 减少),想到讨论 \(a\) 和 \(b\) 的大小关系。

同时采用邻项交换的想法,当 \(a<b\) 时,对于 \((a_1,b_1),(a_2,b_2)\),不妨钦定 \(a_1\le a_2\),然后分析可以得出 \(12\) 和 \(21\) 的代价;

\(a>b\) 时同理,但你发现 \(a_1\le a_2\) 时无法判断大小,此时要换成钦定 \(b_1\le b_2\).

排序后发现先做 \(a\le b\) 来增加内存是更优的,于是也不需要对如何拼接两部分讨论了。扫一遍求答案即可。

bonus: 还存在推式子做法,不过最后还是要分讨。


AT_dp_X

这种限制肯定要背包。但承重的限制不好确定转移顺序。

于是考虑用贪心来确定转移顺序。分析若 \(x\) 放在 \(y\) 上方能比 \(y\) 放在 \(x\) 上方承受更重的物品,此时 \(x\) 和 \(y\) 之间的关系,然后排序,靠前的物品放在上方更优。

然后按照这个顺序在底部加入物品转移,此时总重除自身外就是承重,可以方便地判断,直接 \(01\) 背包即可。


AT_agc023_F

题目中的顺序限制 dfs 序完全可以满足,于是开始考虑 dfs 做。可以对子节点邻项交换然后排序。但样例 \(3\) 告诉你下一个点可以在全局范围内任意跳,所以 dfs 做不了。

既然是全局问题,那直接把所有点加入堆全局排序。堆顶的元素都希望尽早走到,于是将其与 \(par\) 合并,这样 \(par\) 一被走到就可以直接走下来。用 Dsu 维护这个过程,并在合并时统计答案。


P7831

首先可以有一个直观的 dp。设 \(f_u\):从 \(u\) 开始无限游走的最小初始资产,然后对于边 \((u,v,r,p)\) 有 \(f_u\leftarrow \max(r,f_v-p)\). 但图上有环没法做。

观察性质:

  • 若某点没有出边,则其一定没有答案(走不到环)。
  • 若初始资产为全局最大的 \(r\),则一定可以不被限制。

于是先删掉所有出度为 \(0\) 的点,然后按 \(r\) 降序遍历每条没被删的边,然后可以令 \(f_u=r\),答案不会比这个更小,然后删掉这条边。

若出现出度为 \(0\) 的点,再用上面的式子转移,然后删掉这个点。重复做到没有点就得到答案。


P2751

使 \(n\) 个工件尽早完成 A 工序,必然选择所有完成时间中最早的前 \(n\) 个。于是把 \(m_1\) 个机器的完成时间加入堆,重复做 \(n\) 次即可。

同理可以求出 B 工序的前 \(n\) 个完成时间。然后显然首尾配对可以最小化最晚完成时间。


29

AT_arc098_D

正难则反,考虑把过程倒过来,记 \(C_u = A_u - B_u\),则进入点 \(u\) 至少要有 \(\max(0,C_u)\) 元,且第一次进入时获得 \(B_u\) 元。那么这个过程中钱数是单调不降的。

既然这样就希望能一次把邻域内的能走的点走完。考虑根据 \(C_u\) 建出 kruskal 重构树:按照 \(C_u\) 升序依次激活每个点 \(u\),若此时邻域内有其他已经激活的点,则将 \(u\) 向这个点所在连通块的根连边,并令 \(u\) 成为新的根,这样父权值总是大于子权值。

于是策略就是每到一个点就把其子树内所有点都走完。设 \(f_u\) 为从 \(u\) 子树内走到 \(u\) 的最小初始钱数,\(s_u\) 为 \(C\) 子树和。

那么有转移 \(f_u=\min\limits_{u\to v}\{\max(f_v,C_u-s_v)\}\)。最终答案为 \(f_{rt}+s_{rt}\).


P3523

显然首先可以二分。然后判定能否使用 \(m\) 个标记在 \(mid\) 步内覆盖所有关键点。

考虑自下而上递推,记录当前最远未被覆盖的关键点和最近的标记,维护完信息后分讨得出当前点是否必须标记。


UOJ839

首先把原序列看作一个操作。对每个操作维护 nxt 表示其开始覆盖的位置。

逐位贪心,每次取出 nxt 能覆盖到当前位且最大的数,将这一位的答案设定为它。

然后找出这一位是最大值的操作中最小的右端点 \(R\),将这一位上其他所有操作的 nxt 与 \(R+1\) 取 \(\max\).

因为这一位选最大后至少 \(i\sim R\) 全都会被确定,不再可能被其他覆盖。


P6005

首先忽略天数的影响。直接 dp 计算每天每个点可能获得的最大钱数。

即使这样也只有 \(O(nm)\). 直接枚举天数减去 \(C\times T^2\) 即可。


P8186

每头牛向其可能的交换对象连单向边,置换环上的牛都能换到礼物。

判环使用 Floyd 传递闭包,对于 \(x\to y\),当 \(f_{x,y}=1\land f_{y,x}=1\) 时有环且 \(x\) 可以换到 \(y\)。


30

NOICA R6T1

第一眼看出来这个数每次翻倍,爆搜层数 \(O(\log x)\),加上记忆化感觉很可做。但是即便如此每次枚举下次加的数仍然耗费了大量时间。

于是你发现这个东西从后往前做就可以后缀和解决,dp 就行了。


NOICA R6T2

首先注意 \(k\le 10\). 如果建分层图的话空间会炸,于是写了个 Dijkstra 的 dp。现在看起来这没有任何道理,不知道为什么过了 \(7\) 个点。

既然 \(k\le 10\) 应该直接一点:状压 dp 来考虑 \(k\) 个点走的顺序,类似 Hamilton 路径。点与点之间的距离直接 \(k\) 次单源最短路求得。

补题的时候因为忽略 \(k=0\) 的情况和 \(2^k\) 写成 \(2^n\) 调了半天,糖完了。


NOICA R6T3

对这种东西构造二位前缀和来达到它,发现是主副对角线上的一串 \(1\) / \(-1\). 那么这个东西直接做对角线差分就行了。

赛时想到了这里,但实际上要处理一对乱七八糟的边界问题,最后调不出来干脆换暴力。

实际上根本不用这么麻烦,边界难考虑就去掉边界:允许负数和超过范围的数存在,它们的范围至多是 \([-n,2n]\). 最后在 \(3n\times 3n\) 的网格上直接做就好了。


NOICA R6T4

图论建模题。考虑 \(A_i\) 和 \(B_i\) 连边,那么交换两者相当于对边定向,有出边的归属 \(A\),有入边的归属 \(B\).

那么 \(\operatorname{mex}(A)\) 就是最小的出度为 \(0\) 的点,\(\operatorname{mex}(B)\) 同理。若对于一个点有入边也有出边,则认为它能同时在两个集合。

然后 \(1\sim n\) 被划分为若干个连通块。若某个连通块有环,则叶子(即度数为 \(1\) 的点)需要被划分到 \(A\) 或者 \(B\)。这样把所有这样的点都固定分到 \(A\)。

若某个连通块无环,则不妨令其中最大点为汇点(分给 \(B\),其邻域内所有点指向它。显然不劣),其余叶子就为源点。

这样把尽量多的点扔进了 \(A\),可以使答案更优。因为每个点在 \(A\) 还是 \(B\) 造成的贡献是等同的,集中在 \(A\) 反而能凑出更多的连续段。