F - Fuel Round Trip
注意到路程分成了两段,所以我们也按两段 dp。
设 \(f_{i,j,k}\) 表示到第 \(i\) 个加油站,来程加油后油量为 \(j\),回程加油后油量为 \(k\) 的最小代价。
初始对于 \(0\le i\le h\),有 \(f_{0,h,i}=0\)。
考虑刷表法转移(\(i\to i+1\)),令 \(d=x_{i+1}-x_i\),然后根据在哪一段路程加油分类讨论:
- 不加油:
需要满足 $j-d\ge 0$ 且 $k+d\le h$。
- 来程时加油:
需要满足 $j-d\ge 0$ 且 $k+d\le h$。
-
回程时加油:
……此时发现不太好搞,如果直接枚举容量,那么我们无法判断加油前的容量是多少。于是我们修改状态的定义:
\(f_{i,j,k}\) 表示到第 \(i\) 个加油站,来程加油后油量为 \(j\),回程加油前油量为 \(k\) 的最小代价。
这样前面的转移,初始条件都不变。然后就很好转移了,枚举 \(i+1\) 处的返程容量 \(k\),那么:
需要满足 $j-d\ge 0$ 且 $\min(k+F_{i+1},H)\ge 0$。
这样最后的答案就是 \(\min_{i=0}^{h}f_{n,i,i}\)。
时间复杂度 \(O(n^3)\)。
G - Slot Strategy 2 (Hard)
考虑枚举最终字符 \(d\),然后二分判定。
假设当前时间为 \(t\),那么对于每一行,下标在 \([1,t]\) 内值为 \(d\) 的位置都可以选。由于每个位置只能被一行选中,那么可以转换为一个二分图匹配问题:
以每一行为左部点,下标为右部点。对于每一行 \(i\),如果 \(s_{i,j}=d\) 且 \(j\le t\),那么连边 \(A_{i}\to B_{j}\),然后检查是否存在完美匹配即可。
这里需要注意一点,由于每个时间不能重复选,所以 \(t\) 最大会到 \(n\times m\) 级别,这需要我们隐式地将字符串 copy \(n\) 次。而且,此时二分图的点数和边数都是 \(O(nm)\) 级别,无法通过。
但是左部点数量很少,由 Hall 定理我们可以知道,只要满足 \(|T|\le |N_G(T)|\) 就一定存在完美匹配。因此对于每个左部点,只需要连出去 \(n\) 条边即可。
这样点数和边数就都降到了 \(O(n^2)\) 级别。总的时间复杂度是 \(O(n^3d\log(nm))\),就能过了。其中 \(d=10\)。
实现时我用了 map
给右部点标号,所以还要多个 \(\log\),但是跑不满,所以能过。