10 月做题记录

· · 个人记录

CF2146E Yet Another MEX Problem

经过一定尝试,我们发现区间快速求 mex 并不好做,因为 mex 本身的含义太复杂了,我们尝试解构 mex,即考虑其定义:不包含于 a 的最小自然数。我们尝试考虑所有不包含于 a 的自然数。

对于数列 a,以及 x \notin a,我们记 g(a,x)a 中大于 x 的数的个数。若 x \in a,我们规定 g(a,x)=0

显然,w(l,r) = \max_x g(a_{l..r}, x),故

ANS_r = \max_{1 \le l \le r}\max_x g(a_{l..r},x)

然后就是常见的、类似交换求和的技巧:

ANS_r = \max_x \max_{1 \le l \le r} g(a_{l..r}, x)

我们在扫描 r 的时候维护关于 x 的数列:b_x = \max_{1 \le l \le r} g(a_{l..r}, x)

单个的 b_x 如何计算呢?

显然 l 一定是选择使得 a_{l..r} 不包含 x 的最小值。由这一计算方法,我们发现可以用线段树维护。需要区间加、单点修改和区间 max。

小结

第一步看似复杂化了问题,但实际上给了我们更多的操作空间,因为 mex 是一个被封装过的概念,我们对其进行拆解可以获得更多信息。

这与一些和式技巧十分相像。同时这也是一个比较一般的方法可以经常尝试使用。

P12427 [BalticOI 2025] Tour

这种题目一般要么乱搞(但是失败了),要么重建图,把奇怪的关系封装在图里,然后用标准算法跑。

我们以边为点,以转移关系为边建图。此时边数为 m^2,我们考虑增加中转点减少边数,但由于有颜色限制,我们不能直接用原图的点当中转点,而是根据二进制拆点,因为两个颜色不同,一定存在一个位不同。

我们用 id(x,j,b) 表示原点 x 对应中转点,其满足指向其的点颜色第 j 位都为 b,其指出点颜色第 j 位都为 \neg b

最后 DFS 找环即可。

P10596 BZOJ2839 集合计数

公式要背:容斥原理 & 二项式反演

$$ \begin{align} f_k = \binom{n}{k}(2^{2^{n-k}}-1) \\ f_k = \sum_{k\le i\le n}\binom{i}{k}g_i \end{align} $$ 对 $(2)$ 应用二项式反演得到 $$ g_k = \sum_{k\le i\le n}(-1)^{i-k}\binom{i}{k}f_i = \sum_{k\le i\le n}(-1)^{i-k}\binom{i}{k}\binom{n}{i}(2^{2^{n-i}}-1) $$ **小结**: 做题的时候也可能先想到用 $(2)$。 ### 审题:P11922 [PA 2025] 叠积木 / Wieża 塔的大于号看成大于等于。 ### P11912 [PA 2025] 集合 2 / Zbiory 2 再次被构思题创飞,[solution](https://www.luogu.com.cn/article/eq3bszxc)。 ### 典:P11860 [CCC 2025 Senior] 熔岩路 / Floor is Lava 感觉是很经典的优化建图。 首先我们以边为点重新构图就能很方便地确定边权跑最短路,但一个点周围地左右边构成完全图,所以需要优化。 由于边权是由点权(新图)差得到的,所以发现可以删到只剩一条链,链上点权有序。 ### P13691 [CEOI 2025] highest 很好地强化了我对倍增地理解。 倍增地本质是将**操作序列**进行**压缩**。 我们的思路是用 $f_{j,i}$ 表示从 $i$ 花费 $2^j$ 能跳到的最远点。但仅仅这样无法转移,也无法解决询问。 原因是对于某些操作序列,我们花费 $2^j$ 可能跳到某个 `2` 的“中间”。于是我们在用 $g_{j,i}$ 表示花费 $2^j-1$ 跳的最远距离即可。 因为能挑到的位置显然是连续的,所以可以用 ST 表转移。这有一个细节,理论上从 $i$ 花费 $1$ 不能仍停在 $i$,但我们不用管类似的情况,因为总是不优。 查询时因为不能存下 $n \log^2 n$,所以要离线做“整体倍增”。总复杂度 $(n+m) \log^2 n$。 ~~不知道单 $\log$ 怎么做的。~~ ## R19 ### T1 可以发现每个前缀永远都是在一个区间内的,因此最后一定形如从某个位置开始每次向左或者向右加数,并且一个数是从左还是从右加只和它后面的操作次数的奇偶性有关。 因此倒着扫一遍,维护操作次数的奇偶性,然后判断当前数字是加在前面还是后面。 时间 $O(n+m)$。 **小结**:赛时为了给 $a$ 排序用了一个计排,T 了。实际上我们只需要 $a$ 的 $cnt$ 即可。 ### T2 $f(n)=n-\varphi(n)$,其中 $\varphi(n)$ 为欧拉函数。 注意到如果 $n=pq$,其中 $p,q$ 为不相同的质数的话,$\varphi(pq)=(p-1)(q-1),f(pq)=p+q-1\Rightarrow p+q=m+1$。 注意到在 $10^9$ 范围内哥德巴赫猜想是成立的,并且我们可以直接从小到大枚举较小的那个质数,判断 $m+1-p$ 是不是质数,在本题范围内枚举的量是很少的。 **小结**:因为这是个构造题,所以 $n$ 很可能是某个特殊形式的,我们需要多做尝试。 ### T3 注意倍增数组开的顺序要根据循环嵌套的顺序来,内层循环灭据的指标要开在第二维。 #### 解法 1 路径 $p,q$ 有交 $\Leftrightarrow $ $p$ 的 $lca$ 在 $q$ 上或者 $q$ 的 $lca$ 在 $p$ 上。 因此可以算光覆盖了询问的 $lca$ 的权值和,加上询问覆盖的光的 $lca$ 的权值和,减掉 $lca$ 相同的情况。 我们先思考一个 $lca$ 被光覆盖的权值和如何计算,显然就是一个路径加,单点求值。 另一个问题是单点加,路径求和,但显然可以转化成上述情况。 所有的都可以用树上差分 $O((n+m+q)\log n)$ 维护。 **小结**:做题的时候要维持清晰,不时总结一下当前的进度,比如转化为了什么问题,有什么信息。 #### 解法 2 根据点边容斥,一棵树总是满足点-边=1。而路径的交还是路径,路径也是树也符合点边容斥,因此我们可以求出覆盖每个点的路径个数,减掉覆盖每条边的路径个数,那么每个相交的路径会恰好被计算一次,同样是树上差分。 **小结**:路径求和只要是静态的是用不到树剖的。另外**点边容斥**很经典。 ### T4 不妨设 $x<y$,$=$ 的情况是若干条链是容易处理的。 设 $g=\gcd(x,y)$,那么 $\bmod g$ 不同的点是独立的,接下来考虑 $x=x/g,y=y/g,\gcd(x,y)=1$​。 #### 解法 1 建立一个网格图,$i$ 的坐标是 $(\lfloor \frac{i}{y} \rfloor,(i\times x^{-1})\bmod y)$,那么 $+y$ 就是向下一行连边,$+x$ 就是向右\向右下连边,其中最后一列的右侧是第一列。 这样我么能得到一个网格图,考虑直接按行 $dp$,用类似轮廓线 dp 的记录当前轮廓线上每个点是否选了,这样的复杂度是 $O(n2^{y})$。 注意到我们还可以反过来对列 dp,但是这样需要记录第一列和最后一列之间的边选择的状态,时间复杂度 $O(n2^{2(n/y)})$。 把 $y$ 按照 $\leq \sqrt {2n}$ 分治,即可得到 $O(n2^{\sqrt {2n}}) $ 复杂度的做法。 #### 解法 2 从一个点出发进行 BFS,将点按 BFS 序排成一行,可以认为有边相连的两点不会隔太远,然后跑 $x,y \le 15$ 的做法(即只记录前最后的 $15$ 个点)。 #### 小结 两种做法都做了一件事,即对点重新排列使得边不会跨越太远。 ## M14 ### A 简单换根 DP,要二进制拆位。 ### B 先考虑一个区间 $[l,r]$ 如何解决。设最大 $highbit = p$,其出现次数为 $c$。 于是当 $c$ 为奇数,且 $len\ge 2$ 的时候 $G(l,r)=2^p$。当 $c$ 为偶数的时候,$len \ge 5$ 时 $G(l,r)=0$。 对于 $len \le 4$ 的情况,我们直接暴力计算。 对于处理询问,我们可以预处理一些前缀和之类的东西来计算,并不困难。 ### C(待补) $n\le 10$ 时只需暴力枚举所有可能的树. $k=0$ 时只需判断 $n$ 是否形如 $2^k-1$. $k=1$ 时可以暴力枚举在满二叉树上不平衡的节点, 是否合法只与此节点的深度有关. 或者直接判断 $n$ 是否形如 $2^p-2^q-1$. 对 $k$ 较大的情形, 考虑如下对树的刻画: 从上往下考虑, 假设当且节点高度为 $h$, 则有两种情况 + 他有两个高度为 $h-1$ 的子树. + 他有两个高度分别为 $h-1$ 和 $h-2$ 的子树. 按 $h$ 从大到小处理, 只需关心有多少已经生成的节点高度是 $h$ 和 $h-1$, 在动态规划时记录有几个不平衡节点即可. 直接实现此做法的时间复杂度约为 $O(n\log n\cdot k^3)$. 事实上, 我们不关心具体的 $h$, 因为假设有 $x$ 个高度为 0 和 $y$ 个高度为 -1 的点, 总会生成出一棵总点数为 $2x+y-1$ 个点的树, 因为每次合并两个点, 生成一个点. 假设有 $x$ 个高度为 $h$ 和 $y$ 个高度为 $h-1$ 的点, 有 $k$ 个不平衡节点的方案数为 $f_{x,y,k}$, 则转移时枚举 $x$ 个种有 $c$ 个不平衡的儿子, 转移到状态 $f_{2x+y-c,c,c+k}$. 根据刚才的观察, 我们只需要求出所有 $2x+y-1=n$ 的 $f_{x,y,k}$ 的值. 而上述转移时 $x$ 几乎总是除 2. 使用记忆化搜索倒过来转移, 总共扫描到的状态数为 $O(\log n \cdot k^3)$. 每次枚举转移时间复杂度即为 $O(\log n \cdot k^5)$, 事实上常数很小, 可以通过. ### D 根据传统的 dp 过程,维护 $cur$、$ans$ 和 $dif = cur - ans$。 每次执行 $cur = cur + a_i, \quad dif = dif + a_i$。如果 $cur < 0$,则 $dif -= cur, \quad cur = 0$。如果 $dif > 0$,则 $dif = 0$。不需要显式地维护 $ans$。 考虑将所有数都表示成 $\sum c_i \cdot 2^i$ 的形式,其中 $c_i = 0, 1, -1$。 则所有加法和减法操作均摊只需要执行 $O(1)$ 次。使用 set 维护这几个数即可。 使用 set 或者主席树直接维护 $1$ 的连续段也是正确的。 部分分是通向正解的阶梯。 **小结**:因为我们维护的庞大数字不能快速地比较大小,但是能快速判断与 $0$ 的大小关系,于是 $a<b \Leftrightarrow a-b<0$ 即可。 --- ### AT_arc104_d [ARC104D] Multiset Mean **经典 trick**:一般平均值需要和元素个数搭配才能和总和相互转化,但平均值为 $0$ 时是特殊的。 于是我们枚举 $x$。将所有元素减去 $x$,即求在 $[1-x,n-x]$ 中取数使得和为 $0$ 的方案数。这是一个多重背包。 我们记 $f_{i,j}$ 为前 $i$ 个元素总和为 $j$ 的方案书。但是如果正负物品混到一起,写起来有点麻烦。 我们可以把正负分开处理,$f$ 仅记录正数情况,因为负数是对称的,$0$ 的选取是任意的。于是 $$ ANS(x) = (k+1)\sum_{0 \le j \le n(n+1)k/2}{f_{x-1,j}f_{n-x,j}} - 1 $$ 多重背包可以前缀和优化,总复杂度 $O(n^3k)$。 **关于前缀和优化多重背包** ```cpp f[0][0]=1; int sum=0; rep(i,1,n){ sum+=i*m,l+=m+1; rep(j,0,i-1) f[i][j]=f[i-1][j]; rep(j,i,sum) f[i][j]=(f[i-1][j]+f[i][j-i])%P; int l=i*(m+1); per(j,sum,l) f[i][j]=(f[i][j]-f[i][j-l]+P)%P; } ``` 最后一个循环是处理物品数量的限制(前缀和 $\rightarrow$ 区间和),是和完全背包的区别点。 ### P11131 【MX-X5-T3】「GFOI Round 1」Cthugha #### 解法 1 建有向图,指向一个点的边权为其点权。跑 SPFA,在 SLF 和 LLL 优化的加持下可以通过(但不会 LLL,只用 SLF 会 T 一个点)。堆优化也可以。 注意 SPFA 判环中,$cnt_x$ 表示经过了几条边,所以计算应该是和松弛放到一起,而不是直接自增。 #### 解法 2 建无向图,边权为两点权和。对于无解情况,我们发现当且仅当相邻点权值之和为负数。 于是可以跑 Dijktra。 ### P10715 【MX-X1-T3】「KDOI-05」简单的序列问题 **转化 1**:显然可以先对 $a_i$ 取模。$S$ 会有一个直接关于 $a$ 的计算方法:从第奇数个 $1$ 走到第偶数个 $1$ 之前的段的长度和(虽然这个计算方法是无关紧要的)。 **转化 2**:关键转化,观察转化的费用是两点权值和,涉及交换的问题我们处理起来是困难的,于是考虑把一次“交换”拆解成两次“改变”,花费为 $c_i$。我们发现,只要最终 $0/1$ 数量对的上,总存在交换方案与之效果相同且花费相同。并且显然对于任意交换方案,也存在与之对应的改变方案。 然后显然就可以 DP 了,可以滚动数组优化。 MicroSun 指出这题可以从区间翻转的角度解决。 如果写了有返回的函数却没返回,则会发生不可预知的错误,这体现了 `-Wall` 的重要性。 ### P11218 【MX-S4-T2】「yyOI R2」youyou 不喜欢夏天 有点意思。最大子段和变种。 **Case 1**:没有“半选”,此时 `00` 令 $sum$ 减 $1$,`01` 和 `10` 不变,`11` 令 $sum$ 加 $2$。 **Case 2**:有“半选”。因为“半选”在数量不超过 $2m$ 时是纯纯负收益,所以我们可以认为一开始就欠了 $2m$ 的价值。补上来了就是合法解,没补上来虽然非法,但一定不如 Case 1 的答案,所以无所谓。然后最大子段和,注意需要记录前一个位置的选择情况。 ### 经验:P11219 【MX-S4-T3】「yyOI R2」youyou 的序列 II 这种题一看就是要分析一个结论来高效判断输赢,因为这个博弈过程硬做实在太复杂了。 先考虑 $[1,n]$ 上的博弈问题。 零散地分析一些性质: 1. $\max_{1 \le i \le n}a_i \le w_1$ 是 youyou 赢的必要条件。 2. 如果存在两个点 $x,y$ 能被 yy 覆盖,但是不能被 youyou **一次**覆盖,那么 youyou 会输。 性质 2 的否命题同样正确,即:如果对于所有 yy 能覆盖的点,youyou 可以一次覆盖,那么 youyou 会赢(当然假设性质 1 的条件成立)。 剩下的就是维护 yy 能覆盖的最左最右点,可以用一个数组表示长为 $c_2$ 的区间和,线段树维护,查询可以二分。 最后判断一下边缘情况。 **小结**: VP 的时候基本把重要的东西分析得差不多了,比如 youyou 要输的话需要有两个点形成牵制,但就是没有有效的总结出结论。 一个有效得方法是把已知得结论列下来,写到草稿纸上。 总的来说,做题的时候应该自信一点,坚决一点,细致一点。 ### P11220 【MX-S4-T4】「yyOI R2」youyou 的三进制数 首先要想到将原题目转化为图论模型,否则一切都无从下手。 然后观察一个性质:所有 $b$ 与 $c$ 的交点都是同一个。这点比较显然。 然后是圆方数相关计数,非常简单。可以树上差分实现。 ### 待补:P11236 [KTSC 2024 R1] 水果游戏 一个经典的套路是:如果我们对一个问题有迭代做法,那么我们很可能可以用线段树进行多次查询的加速。 **OBS 1**:如果出现一个数小于两边,则两边相当于被隔开。 ### 二维平面视角:P14255 列车(train) 将区间信息放到二维平面上问题将变得易于解决。 将区间的左端点看作横坐标,右端点看作纵坐标。我们所维护的删除区间一定是递增的。 可以用线段树维护 $x$ 轴上的某种“拐点”,暴力单点修改,用势能可以说明复杂度。 **小结**:二维平面、图,都是常用视角。 ### AT_arc107_d [ARC107D] Number of Multisets 朴素地设计 DP:$f_{i,j} =$ 大小为 $i$,和为 $j$ 的多重集个数。 **转移**: 1. 若有 $1$,$f_{i,j} \leftarrow f_{i-1,j-1}$。 2. 若无 $1$,则可以由其他情况整体除以 $2$ 得到,即 $f_{i,j} \leftarrow f_{i,2j}$。 **小结**:可以和 AT_arc201_b 放到一起看。与 $2^k$ 相关,涉及整体乘除 $2$ 进行归化的思想。 ### P11234 [CSP-S 2024] 擂台游戏 ### *AT_arc186_d [ARC186D] Polish Mania **这题是不是不转换也行?** 一个显然的观察:一个 Polish 序列唯一对应一颗树。 我们要统计某种复杂序列的数量,理想的方法是找到等价条件。 **等价条件**: 1. $\sum a_i = n-1
  1. \forall m<n, \sum_{1\le i\le m}a_i \ge i

然后类似数位统计,加上格路计数。需要用到经典的反射容斥。

*QOJ7649 序列

非常像 BJMX 的一道题,观察到一个递归结构然后可以 DP。

一个神秘技术:n 固定时,f_{n,m} 是关于 m 的多项式,于是用拉格朗日插值解决 m 很大的情况。

*AT_arc117_e [ARC117E] Zero-Sum Ranges 2

连续段 DP,熟悉不同角度的 DP。

*AT_arc118_e [ARC118E] Avoid Permutations

考虑用所有路径减去经过了黑点的路径得到答案,这里需要一个容斥。

考虑用 f_{i,j,k} 表示走到 (i,j) 经过 k 个黑点的路径数。如果黑点的排布是任意的,那么这样就可以了。

但本题黑点是按照排列来排布的,即每行仅有一个,每列也仅有一个,所以加两个 0/1 位来表示即可。

反悔贪心与模拟费用流:P11268 【MX-S5-T2】买东西题

可以建费用流,但是没用,不如匹配模型简洁,而且增广模式不是按照 SSP 算法的,如果先入为主会陷入误区。

我们考虑将物品按 a 升序排列,优惠券按 w 升序排列。不妨假设所有物品都先使用折扣。

考虑增量过程,物品 i 如何抉择:

  1. 直接吃折扣。\Delta=0
  2. 拿一个没有匹配的优惠券。\Delta=(a_i-b_i)-v_jj 为某个优惠券。
  3. 拿一个有匹配的优惠券,看上去会引起一系列变动,但实际上发现被夺走优惠券的物品如果去拿另一个券,不如直接让 i 匹配。\Delta=(a_i-b_i)-(a_j-b_j)j 为某个优惠券匹配的物品。

我们可以考虑为优惠券赋一个新权值 d

  1. 未匹配,d=v
  2. 匹配 jd=a_j-b_j

算法过程会保证当前的答案为考虑前 i 个物品的最优解(一般的贪心都是如此)。

P10997 【MX-J3-T4】 Partition

十分巧思的一题,把贡献拆一拆,可以等价转化为两次可重叠的染色,并且两次是独立的。

经验:P11064 【MX-X4-T4】「Jason-1」一步最优

当我们遇到一个与经典问题的相关的问题时,不要怼着一种经典算法想,因为不同算法有不同优势。像这里我没想起来经典的线段树维护最大子段和。

P11158 【MX-X6-T4】夢重力

改变统计顺序。

没有关键点的子矩形贡献为 2\binom{n/2}{2},有一个关键点的贡献为 1

后面的计数没做出来。

暴力是 O(n^2) 的,我们考虑一行一行考虑,每行考虑纵向的一段区间,维护区间内的点,然后就可以根据点之间的空隙数数了。

之前老想用神秘数据结构。

警示:P5058 [ZJOI2004] 嗅探器

虽然这题极为简单,但还是有个细节要注意:判断割点 u 是否可以为信息中心,要用 dfn[t] >= dfn[v] 而不是 dfn[t] > dfn[u]。因为 u 为割点,且 t 在子树 u 中,并不能说明会断开,因为仍可能在同一个点双内(割点不一定会断开一切儿子)。

P7907 [Ynoi2005] rmscne

注意到合法性的“传递性”,这题就容易了。还有子区间是一个后缀的前缀。