应该是暴力。这里有个主体思路,我们完全可以贪心地将当前背包里的食材删掉,直到每种出现过的食材数量刚好为 1。因为我们保留更多的是没有用的。那么我们就可以用二进制数表示 x 种食材的出现状态了。
同时,可能存在当前的一个状态 s,将 s 与第 i 个采集点结合时出现了背包装不下,单删掉 s 中的几个 1 后能够装下且更优。这启示我们,对于一个 s 实际上是可能转移到其一个子集会更优。既然都能转到子集了,那么在第 i 个采集点的时候,记 t_i 为这个采集点每个食材的出现状态,我们就完全可以用一个与 t_i 不交的状态 s 来转移。
我们对于当前能够达到的所有状态 s 去转移 s'。如果 s' 已经被转移过了,那显然是没有必要再转移一次的。那么我们就能保证每个状态最多被转移 1 次。同时,因为 s 的所有子集也可以去转移,所以算上枚举子集的复杂度就是 O(3^x) 的。
考虑到,对于一个状态 s',如果它可以通过 t_i 和 s 得到,当且仅当 s' 是 t_i \cap s 的子集。根据 Sub2 分析的第二个自然段,可以进一步得到:当状态 s' 能被转移到时,需要满足 s' 的所有子集都能被转移到。那么我们拿一个 set 来记录所有合法的状态,如果一个状态可以得到,我们去推它的一个超集,动态插入所有从不合法变成合法的超集。那么之后任意时间,这个状态都没有用了,可以直接删掉。
现在考虑枚举超集。根据上述的条件,我们得知 s' 合法的前提是其子集都合法,那么我们枚举超集的时候就只需要枚举所有 |S|=|s'|+1 的 s' 的超集,只要 S 删掉任意一个 1 得到的集合都合法,那么它就合法了。为什么不需要枚举 |S|=|s'|+2 的超集?很显然,当 |S'|=|s'|+1 且 S' 是 S 的子集时,如果 S' 仍不合法,那么 S 显然不合法。如果 S' 合法,那么 S 将在枚举 S' 的超集时被枚举到。所以这样就是对的。
因为这样我们保证了对于任意时刻,不存在 set 中的两个状态 a,b,有 a 是 b 的子集。所以 set 中最多 x 个状态。额,分析不来了。复杂度未知,应该不是很大。
貌似不删除的复杂度是 O(2^xn) 的,也能过。
AT_agc017_f
陈年老题,听了若干遍都没补。
很显然,一条路径 p 我们可以用唯一的二进制数 s 表示出来,其中 s_i=0 表示第 i 步向左走,反之同理。不难发现,当我们走到了第 j 行,那么上一条路径前 j-1 步是没有用的。于是就可以考虑轮廓线 DP。
因为强调在上一条路径的右边,不妨让这条路径初始时与上一条路径完全重合。那么只需要考虑拐弯的情况。定义状态函数 f_{i,j,s} 表示第 i 条路径,走到第 j 行,每一步的状态为 s 时的方案数。考虑对第 j 步向左向右的情况进行分类讨论:
直觉告诉我们这题可能只能暴力枚举每个人当总统。那么对于第 i 个人当总统的情况,可以发现当去掉第 i 个人的所有投票后,因为赞成的票数不会增加,所以当第 j 项投票的赞成票数量小于 \lfloor \frac{n}{2}\rfloor 时,是不可能有贡献的。而当数量大于 \lfloor \frac{n}{2}\rfloor 时,在最坏情况下也不会小于 \lfloor \frac{n}{2}\rfloor,所以是一定有贡献的。
那么现在只需要考虑等于 \lfloor \frac{n}{2}\rfloor 的情况。记其下标集合为 s。现在考虑对于一个人 j,那么他的贡献将是:-\sum\limits_{x\in s}^{} [a_{j,x}=1]。可以将 s 看作一个二进制数,其中 x \in s 的位置为 1,记为 t,那么贡献就是 -|t \cup a_j|。所以现在对于第 i 个人当总统的情况,我们就只需要解决除了 i 以外 |t \cup a_j| 的最小值。j \ne i 这个限制很弱,统计最小和次小就行了。
现在问题就变成求 |x \cup a_i| 的最小值。因为 a_i 是 x \cup a_i 的超集,x\cup a_i 是 x 的子集。所以我们可以考虑先处理前半部分再处理后半部分。但是如果取 \min 的话就会出现 x 的答案变成 0 的情况。因为空集是 a_i 的子集同时也一定是 x 的子集。如果我们将 a_i 取反,求 |x \cup b_i| 的最大值,再拿 |x| 减去,就可以用两遍 SOS DP 解决了。时间复杂度 O(m2^m)。
这里只针对了最大值,实际上为了保证 i \ne j 还需要记录次大值。证明可行简单。参考 CSP-J 2024 T4 题解。
注意记录最大值和次大值的时候,需要保证这两个值的编号不同。
P2435
考虑轮廓线 DP。定义状态函数 f_{i,j,s} 表示到第 i 行第 j 列,第 i 行的前 j 列与第 i-1 行的第 j+1~\sim m 列形成的颜色状态为 s 的方案数。那么只需要用 k 进制数表示 s,要满足第 j 列与其左边和上面不同就行了,转移 O(k)。时间复杂度 O(nmk^{m+1})。
AT_arc100_c
简单吧。不难发现,i 可能对 K 有贡献,当且仅当 i 是 K 的子集。那么问题就变成:对于每个 K,在其子集里面选 2 个数 i,j,使得 a_i+a_j 最大。然后取前缀 \max。跑个高维前缀 \max 可以做到 O(n2^n)。
这样的话,如果我们将第 i 个块的值域赋成 [B_i,B^{i+1}),那么会得到 \log_bV 棵线段树。对于跨越值域的情况,考虑均摊分析:因为每个点不增,所以最多会跨越 \log_b V 次。那么暴力重构总的复杂度就是 O(n\log_b V \log n)。而没有重构的情况,直接打 tag 的复杂度是 O(m\log_b V\log n) 的。
那么对于 \min \le x < \max 的情况。因为一个点在块内最多被减 \frac{B_{i+1}}{B_i}\log_b V 次,那么总的复杂度就是 O(B n \log_b V \log n) 的。