2026.5 做题纪要
2026.5 做题纪要
QOJ7504 HearthStone
显然最后的条件是 \(b_1=1,b_i\le b_{i+1}\le b_{i}+1\)。那么可以考虑 dp,设 \(f_{i,j}\) 表示 \(b_i=j\) 的最小代价,有转移 \(f_{i,j}=\min(f_{i-1,j},f_{i-1,j-1})+|a_i-j|\)。
暴力做显然是 \(O(n^2)\) 的,熟知 \(|a_i-j|\) 是一个关于 \(j\) 的下凸函数,猜测 \(f_i\) 也是关于 \(j\) 的下凸函数,归纳发现是对的。于是考虑 Slope Trick 优化,用两个堆分别维护斜率 \(<0\) 和 \(>0\) 的部分即可,复杂度 \(O(n\log n)\)。
P10104 [GDKOI2023 提高组] 异或图
比较二合一的题。首先考虑 \(m=0\) 怎么做,这是一个经典的问题。枚举所有 \(a_i,b_i\) 在二进制下 LCP 的最小值,那么前面的值无法修改,后面的值可以随便取,只需要用 LCP 最小的那个 \(b_i\) 来调整使得异或和为 \(C\) 即可。复杂度是 \(O(n\log V)\) 的。
然后考虑限制,显然我们需要图上容斥一下。假设我们钦定 \(S\) 中的点全部相等,我们需要算出它的容斥系数。这个系数实际上是所有让 \(S\) 中的点连通的选边方案的 \((-1)^{|E|}\) 之和。设 \(f(S)\) 表示图连通时的系数,容斥掉不连通的方案即可,这一部分复杂度是 \(O(3^n)\) 的。
很显然对于一个 \(b_i\) 相等且大小为奇数的分组,我们只关心其中 \(a_i\) 最小值。于是设 \(dp(S,T)\) 表示考虑了 \(S\) 中点的分组,其中最小值集合为 \(T\) 的方案数。暴力转移是 \(O(4^n)\),难以通过。
考虑优化,我们将 \(a_i\) 从小到大排序,每次枚举 \(i\) 尝试将 \(i\) 加入分组。如果 \(i\) 已经在分组中就跳过,否则考察此时 \(S,T\) 的性质,容易发现此时 \(S\) 的前 \(i-1\) 位不能有值,而 \(T\) 只有前 \(i-1\) 位有值。所以此时 \(S,T\) 可以被压缩成一个状态,复杂度就是 \(O(3^nn)\) 的了。
做完之后枚举集合 \(T\),对每个最小值集合跑一遍最开始的 dp,复杂度就是 \(O(3^nn+2^nn\log V)\) 的,可以通过。
P9732 [CEOI 2023] Trade
假设一个区间的代价是 \(w(l, r)\),容易发现 \(w(l,r)\) 满足四边形不等式,那么我们同样可以用决策单调性优化,复杂度 \(O(n\log^2 n)\)。这告诉我们求区间代价最值的时候也可以采用决策单调性。
然后考虑第二问,这个比较困难。对于这种题目,我们发现它的区间个数比较多,所以考虑去掉一些无用区间。考虑两个区间满足 \(l_1<l_2<r_2<r_1\),容易发现根据四边形不等式我们只需要保留 \([l_1,r_2],[l_2,r_2],[l_2,r_1]\),也就是说我们可以去掉只有包含关系的区间,那么双指针一下剩下的区间就只有 \(O(n)\) 个了。
GYM103428C Assign or Multiply
首先用原根把乘法改成加法,然后有转移 \(f_i\to f_{(i+a_j)\bmod p}\)。暴力转移 \(O(np)\),用 bitset 可以除以 \(w\) 但是没什么用。
不过这还是给我们一些启发,因为这个 dp 的值域是 \(\{0,1\}\)。考虑上述转移有用当且仅当 \(f_i=1,f_{(i+a_j)\bmod p}=0\),不妨将其放宽至 \(f_i\ne f_{(i+a_j)\bmod p}\)。如果我们将所有满足条件的 \(i\) 连边 \(i\to (i+a_j)\bmod p\),那么显然形成若干个环。而环上 \(0\to 1\) 的边和 \(1\to 0\) 的边的数量应该是一致的。而由于 \(0\to 1\) 的边总共只有 \(O(n)\) 条,所以总的边数是 \(O(n)\) 的。
现在我们只需要找到这些值不同的位置,树状数组存一下哈希值然后二分即可做到 \(O(n\log^2 n)\)。
QOJ2562 Fake Plastic Trees 2
首先有一个弱智的 dp:设 \(f(i,j,k)\) 表示子树 \(i\) 割了 \(j\) 条边,当前连通块和为 \(k\) 是否可行。根据经典的树上背包复杂度分析,复杂度是 \(O(nkV^2)\) 的。
然后这种问题我们可以考虑精简信息。经过一些观察后会发现,对于三个状态 \(x<y<z\),如果 \(z-x\le R-L +1\),那么实际上 \(y\) 这个状态是无用的。考虑假设 \(y\) 最终所在连通块和为 \(S\),那么:
- 如果 \(S-y+z\le R\),那么 \(y\) 可以换成 \(z\);
- 否则我们有 \(S-y+z> R,x-z\ge L-R-1\),两者加起来得到 \(S-y+x\ge L\),那么 \(y\) 可以换成 \(z\)。
然后考虑 \(k\) 的极差,由于每个连通块大小为 \([L,R]\) 且割掉了 \(j\) 条边,所以极差应该是 \(j(R-L)\)。那么根据结论可知有用的 \(k\) 只有 \(O(k)\) 个。所以总复杂度为 \(O(nk^3)\)。
P16433 [APIO 2026 中国区] 上升
只能说考场上没做出来就是活该。
考虑容斥,把上升钦定成下降,也就是我们将序列划分为若干个下降段。段内相邻元素贡献为 \((1-w_i)\),段之间相邻元素贡献为 \(w_i\)。这样相比于钦定上升段的好处在于每一段只有最多一个确定元素。
如果没有确定元素,钦定后我们用组合数算一下方案就好了。如果区间 \([l,r]\) 中有一个确定元素 \(p_i\),那么相当于 \([l,i)\) 中所有数要 \(>p_i\),且 \((i,r]\) 中所有数要 \(<p_i\)。这两个限制很难做,不过如果只有 \(<p_i\) 的限制将是容易的,因为我们保证了扫的过程中 \(p_i\) 单调递增,于是只需要记录前面用了多少个数就能转移。
那么考虑进行第二次容斥,将 \(>p_i\) 钦定成 \(<p_i\) 和无限制,容斥系数是 \((-1)^k\)。那么 dp 状态就可以定义为 \(f_{i,j}\) 表示当前处理 \([1,i]\),前面共有 \(j\) 个位置没有限制的方案数。转移时枚举上一个下降段的结尾,如果有确定元素还需要枚举容斥的 \(k\),这样复杂度来到 \(O(n^4)\)。
注意到对于一个有关键元素的段,\(l\to i\) 的转移和 \(i\to r\) 的转移是独立的。于是分步转移可以优化到 \(O(n^3)\)。
事实上这个题做法较多,已知的有零次容斥(延迟钦定)、一次容斥和上面的二次容斥做法。
P16435 [APIO 2026 中国区] 集宝
记 \(S(u,d)\) 表示树上的一个圆。首先考虑暴力,发现每一次我们一定是将 \(x\) 挪到最近的合法点,那么可以做到 \(O(nq)\)。进一步观察 B 性质发现,如果询问区间 \([l,r]\) 满足 \(\cap_{i=l}^r S(a_i,d_i)\ne \varnothing\),那么将 \(x\) 直接挪到这个交集中一定是不劣的。
从这个性质出发来考虑,我们找到 \(l\) 为左端点的最大的 \(k\) 满足 \([l,k]\) 中所有邻域交集不为空。第一步 \(x\) 一定直接挪到这个交集中。此时由于这个交集和 \(S(a_{k+1},d_{k+1})\) 没有交,根据上面的贪心,在挪到 \(k+1\) 的时候的点是固定的,与 \(x\) 没有关系。这样的话我们就可以预处理这部分情况,具体来讲我们可以差分,将 \((1,1,r)\) 的答案减去 \((1,1,k+1)\) 的答案即可。
所以我们双指针求出每个 \(l\) 对应的右端点,只需要额外处理将 \(x\) 挪到交集中以及从交集中挪到 \(k+1\) 这两个距离。由于邻域求交需要求 LCA 和 \(k\) 级祖先,简单实现可以做到 \(O((m+q)\log m\log n)\),足够通过。
QOJ16841 New Balls
省流:观察样例发现构造就是 zig-zag pattern,然后判断直接看和那条链重合边数最多即可。
认真一点来分析的话就是,考虑 \(2n\) 个点的完全图有 \(n(2n-1)\) 条边,而我们要构造的是 \(n\) 个 \(2n\) 个点的树,边数恰好也是 \(n(2n-1)\)。然后由于操作只能进行 \(n-1\) 次,所以新的树和原来的树必定有至少 \(n\) 条重合的边。如果我们能将这个完全图恰好划分成 \(n\) 个不交的树,那么只有最多一棵树和新树的交 \(\ge n\),那么这个树就是答案。
然后划分完全图是一个经典问题,zig-zag pattern 划分一下即可。
QOJ18206 Guess the Permutation
把 \(0\) 先扔掉,首先考虑如果知道 \(p_x=1\) 怎么做,很显然我们对所有 \(y\) 问 \((x,y)\) 就可以得出 \(p_y=p_z+p_x=p_z+1\)。
但是我们不知道 \(1\) 在哪里,这种题有一个套路是我们可以假设当前的 \(x\) 就是 \(1\),然后在询问的过程中如果有矛盾再往 \(1\) 调整。因为 \(1\) 类似于一个叶子,没有比它小的数,所以一定可以调整到。
所以对于当前 \(x\),我们询问一个 \((x,y)\),我们认为我们确定 \(p_y=p_x+p_z\),然后令 \(y=z\),这样递归下去,一定会在某个时间满足 \(p_y<p_x\)。此时我们再询问 \((x,z)\) 的时候会发现返回值为 \(y\),于是我们就推出了矛盾。这个时候我们确定的信息是 \(p_x=p_y+p_z\)。然后接下来我们需要更新 \(x\) 为 \(y,z\) 中的一个,为了保证复杂度,我们希望每次选的是较小的那个,这样可以保证 \(x\) 每次缩小一半。而确定 \(y,z\) 哪个更小需要额外的两次操作,所以总的操作次数应该是 \(n+2\log n\),可以通过。
QOJ18211 Minesweeper
平面图有一个性质:至少存在一个点度数 \(\le 5\)。我们每次找到度数最小的点然后删掉,这样两个人可以得到唯一的一个拓扑序。
考虑这个拓扑序的性质,对于一个点 \(p_i\),它向 \(p_j(j>i)\) 这种点连的边数应该 \(\le 5\)。所以对于非炸弹的点,把比它靠前且与它相连的炸弹数量减去,那么 \(a'_i\) 应该 \(\le 5\)。于是我们有一个思路是通过 \(a'_i\) 和 \(5\) 的关系来判断它是不是炸弹。事实上发现这是对的,因为对于拓扑序上的第 \(i\) 个炸弹,前面最多有 \(i-1\) 个炸弹,所以我们给它赋值为 \(5+i\) 就可以保证 \(a'_i>5\)。但是对于最后 \(5\) 个炸弹会有问题,不过发现这 \(5\) 个炸弹的位置可以直接用 \(100\) 个比特表示出来,于是就做完了。
【HT-111-NOI】核桃 NOI 周赛 T1
题意:交互库给出两个不同的数 \(a_0, a_1\),第一个人接受这两个数,然后构造一个数 \(k\) 给第二个人;交互库随机把一个 \(a_x(x\in \{0,1\})\) 给第二个人。第二个人需要根据 \(k\) 和 \(a_x\) 求出 \(x\)。\(0\le a_i\le 920,0\le k\le 11\)。
感觉这题神了。我们有一个简单的思路是传 \(a_0,a_1\) 二进制下哪一位不同,然后为了区分我们还需要再传哪个数在当前位为 \(0\),所以 \(k\) 的值域还需要乘 \(2\)。
这个做法垃圾在后面这个区分,所以考虑加强一下条件,如果我们能保证我们能找出一位,使得 \(a_0\) 在这一位为 \(0\) 且 \(a_1\) 在这一位为 \(1\),我们就只用传位数信息了。
那么我们现在可以构造长度为 \(12\) 的串,希望任意两个串满足上面的要求。注意到 \(\binom{12}{6}=924 >920\),所以我们让每个数映射一个 \(\text{popc}=6\) 的串,这样两个不同的串之间一定可以找到这样的一位,然后就做完了。
P14637 [NOIP2025] 树的价值
有关 mex 的问题基本上需要一些延迟钦定,观察到这个题当前子树内比 mex 大的值不是很关键,所以把他们延迟到祖先钦定。设 \(f_{i,j,k}\) 表示 \(i\) 子树内 mex 为 \(j\),当前子树内还有 \(k\) 个空位没有确定的方案。直接做可以做到 \(O(n^4)\),前缀和优化就可以做到 \(O(n^3)\)。
优化的话需要在全局考察 dp 贡献的形式。注意到对于每个 \(i\),它会唯一选择一个儿子 \(v\),然后 \(j\) 会从这个 \(v\) 的 \(j'\) 转移过来。将这样的边 \((i,v)\) 成为关键边,容易发现关键边形成了一个树的剖分。然后接下来 dp 的转移是将子树内的若干个空位填上,以此来增加当前的 mex 值。
注意到如果我们选择 \(v\) 中的空位,那么不如在 \(v\) 处就将这些空位填上,因为当前的 mex 是继承了 \(v\) 的 mex;所以只需要考察非关键边的子树,假如我们点亮了一个空位,那么根据转移,从该点到剖分链的链顶上的所有点的权值都会 \(+1\)。于是总结一下我们会发现,假如我们确定了转移的链剖分,那么对于一个点,其对答案的最大贡献就是这个点根链上的最长连续关键边长度。
于是可以设计一个如下 dp:设 \(f_{i,j,k}\) 表示当前在点 \(i\),当前点所在转移链长度为 \(j\),根链上最长转移链长度为 \(k\)。这样可以直接做到 \(O(nm^2)\)。优化的话需要进一步观察性质,考察对于一个二元组 \((i,k)\),如果 \(i\) 子树内没有长度 \(>j\) 的转移链,那么直接就可以返回了;否则的话我们可以证明,一定存在一种最优解使得 \(i\) 开头的链长度 \(>j\)。所以实际上我们有用的状态只有 \(f_{i,1,k}\) 和 \(f_{i,k,k}\)。直接转移会发现里面有一个树链求和状物,树状数组维护一下,复杂度 \(O(nm\log n)\),可以通过。
P7564 [JOISC 2021] 保镖
好像是经典套路。考虑二维坐标系 \((t,x)\),这样每个游客走的路程就是一条斜率为 \(\pm 1\) 的线段。考虑旋转坐标系,这样的游客走的路程就是横线或竖线,并且线段上有权值,而保镖的行动规则就是向下或向右走,要求走过的线段权值和最大。
先离散化,这样可以形成一个 \(n\times n\) 的网格,网格的每条边上有权值。先 dp 求出从某个交点出发走到右下角的权值最大值。这样对于一个询问,我们只需要考虑从询问点走到某个交点这一部分即可。容易发现我们一定是朝一个方向走,在某条边停下,然后拐弯走到一个交点。所以可以暴力枚举在那条边停下,复杂度可以做到 \(O(n^2+qn)\)。
优化的话可以发现我们对于一个询问点,枚举完停下来的边后贡献是一个一次函数的形式。所以考虑离线扫描线,然后用李超线段树求出这个最值即可。复杂度 \(O((q+n^2)\log V)\)。
QOJ8005 Crossing the Border
首先有一个简单的 dp 是枚举 \(S\) 和 \(T\),令 \(T\) 的最高位大于 \(S\) 的最高位,然后用 \(dp_S\) 更新 \(dp_{S\cup T}\)。这样做的复杂度是 \(O(3^n)\) 的。优化的话我们考虑进行一次折半,我们将 \(S\) 拆成两个部分 \(XY\),这样的话一次转移 \(XY\to X'Y'\) 可以看做 \(XY\to XY'\to X'Y'\),这样的话我们就可以分步转移。
具体的,先枚举 \(X,Y'\) 以及 \(Y'\) 子集 \(Y\),那么它对体积的贡献就是 \(s_{Y'-Y}\)。然后枚举 \(X\) 的超集 \(X'\),它对体积的贡献为 \(s_{X'-X}\),那么此时符合要求的另一半体积贡献应该要 \(\le W-s_{X'-X}\),很明显排序后是一个前缀。所以对两边排好序后双指针就可以求出转移,复杂度 \(O(2^{\frac n2}\times 3^{\frac{n}2})=O(6^{\frac n2})\)。

浙公网安备 33010602011771号