关于转生到异世界的我被要求一天和人 duel CF 100 次要不然在 NOI 只能悲惨打铁然后被 whk 狠狠抽打这件事
关于转生到异世界的我被要求一天和人 duel CF 100 次要不然在 NOI 只能悲惨打铁然后被 whk 狠狠抽打这件事
3. 26
和 cwm duel 了一天 *1900,被暴打。
1216E1. Numerical Sequence (easy version)
预处理之后二分就好。比较简单。AC 记录
1600E. Array Game
博弈
比较巧妙的博弈题。
最重要的一点:取走的数一定是原序列中极长的,严格上升的前/后缀。这是本题的切入点。设极长的前缀为 \(a_1 < a_2 < \cdots < a_{l_1}\),极长的后缀为 \(a_n < a_{n - 1} < \cdots < a_{n - l_2 + 1}\)。
自然想到分奇偶性讨论。可以证明:极长严格上升的前/后缀中至少一个的长度是奇数,是 Alice 获胜的充要条件。具体有三种情况:
- 两个都是奇数:不失一般性地设 \(a_1 \ge a_n\)。那么 Alice 取走 \(a_1\) 以后,两人后续的操作都被固定了:Bob 只能取走 \(a_2\),接着Alice 取走 \(a_3\),一直到 \(a_{l_1}\) 被取走。由于 \(l_1\) 是奇数,所以 \(a_{l_1}\) 一定被 Alice 取走,因此 Alice 获胜。
- 有一个是奇数:不妨设 \(l_1\) 是奇数,则 Alice 只要先取走 \(a_1\) 就可以获胜。这是因为取走 \(a_1\) 之后,序列中极长上升前/后缀的长度都变成了偶数。此时如果 Bob 在前缀中取,Alice 就取走前缀中的下一个数;Bob 在后缀中取,Alice 就取走后缀中的下一个数。由于前/后缀的长度都是偶数,所以最终还是 Alice 取走最后一个能取的数。
- 两个都是偶数:此时 Alice 面对了 Case 2 中 Bob 面对的情况,因此 Alice 必败。
极长上升前/后缀可能会有至多一个数重合,但不影响上述的讨论。AC 记录
1141F2. Same Sum Blocks (Hard)
枚举,贪心
首先排除 dp,因为没法设计能有效刻画当前局面的状态。
然后看数据范围,可以接受一个 \(\tilde{O}(n^{2})\) 的做法。当我们不知道划分出的区间和是什么时,很难入手解决问题,因此我们直接枚举所有的区间和,这总共有 \(O(n^{2})\) 个。
那么现在问题变成了:给定一个数 \(x\),求序列中最多存在几个不交的区间,使得每个区间的区间和都是 \(x\)。可以先把所有区间和为 \(x\) 的区间预处理出来,然后就变成了经典的贪心问题:给定一些区间,求最多能选出几个区间,满足区间两两不交。
把区间按右端点排序,对于一个新的区间,判断其左端点是否大于上一个选择的区间的右端点。如果是,则可以选择当前区间。
在 \(O(n^{2})\) 的时间内把每个区间和对应的区间集合找出来,总时间复杂度 \(O(n^{2} \log n^{2})\)。(其实我不太会分析,不过 \(O(n^{2} \operatorname{polylog}(n))\) 总是对的。)AC 记录
309C. Memory for Arrays
贪心
首先可以发现,先选小的物品一定是不劣的,正确性显然。
但怎么匹配物品和背包呢?我猜测把未选择的最小物品放到剩余容量最小的背包是最优的。这种贪心确实可以通过很多个测试点,但它是错的,有反例:
3 5
3 4 5
1 1 2 4 4
按照上述策略,最多可以放入 \(4\) 个物品(括号前的数代表背包容量,括号后的数代表放进去的物品的大小):
3 (1 + 1)
4 (2)
5 (4)
但实际上可以放入 \(5\) 个:
3 (1 + 2)
4 (4)
5 (1 + 4)
究其原因,是因为在放入物品的过程中,有一部分背包的容量被浪费了。每个背包浪费的容量都不能独自容纳一个新的物品,但可以找到某种方式重新匹配物品和背包,使得这些被浪费的容量“合并“起来,放入新的物品。
目前为止,我们的做法还没有利用”物品的大小是 \(2\) 的非负整数次幂“这个性质,而正解确实与此有关。
下面给出正确的做法:把背包容量按二进制拆分开,也就是说把一个背包拆分成几个小背包。对于上文的样例,三个背包分别被拆分为:
3 = 1 + 2
4 = 4
5 = 1 + 4
拆分之后再执行原先的贪心策略:把物品放入剩余容量最小的背包中,这样就是对的。感性理解,这种策略不会造成”背包的剩余容量可以合并“这种情况。好吧我也不知道该怎么用语言严谨描述正确性,反正对了。AC 记录
3. 27
1611E2. Escape The Maze (hard version)
这题不算很思维,一步一步想就能自然得出解法。
V 的最优策略显然是选定某个叶子节点,然后沿着 \(1\) 号节点到这个叶子节点的简单路径走。如果不存在某个朋友可以拦截 V,那么 V 就赢了。进一步,每个朋友可以拦截的叶子节点构成一个集合,我们要判断这些集合的并能不能覆盖所有叶子节点,如果能,还要求出最少几个集合能覆盖所有叶子节点。
V 往下走时,他的朋友可以往上走。如果他们可以在某个节点 \(u\) 相遇,那么 V 就不能选择 \(T(u)\) 中的叶子节点当作终点。也就是说,每个朋友可以拦截一棵子树内的所有叶子节点。对于节点 \(u\),如果 \(dep_u \ge \left \lfloor \dfrac{dep_{x_{i}}}{2} \right\rfloor\),那第 \(i\) 个朋友就可以拦截 \(T(u)\) 中的所有叶子节点,我们标记深度最浅的 \(u\)。(这一步的实现,可以先 \(O(n \log n)\) 预处理每个节点的 \(2^{k}\) 级祖先,但更简单的方法是 dfs 的过程中用一个栈维护从根节点到当前节点路径上的所有节点)
把节点标记完之后再 dfs 一次,贪心地选择标记的点,就可以得到答案。具体来说,如果点 \(u\) 被标记了,那么就直接选择点 \(u\),而不必考虑其子树内的点。正确性显然。总时间复杂度 \(O(n)\)。AC 记录

浙公网安备 33010602011771号