2026 dmy 模拟赛
第一场
- A
错因分析:没有从式子中最难的部分入手,导致完全没思路。
正解:
-
考虑去掉题目中的 \(\min\),想到从小到大枚举数值构造 \(p\),这样每次填入的第一个数就是最小值。
-
因为要求所有方案的权值和,考虑 dp。发现状态并不明显,所以先推转移。
-
分情况讨论:如果当前的数值填入以前的段,则它的贡献就是这个段的空位乘上 dp 值;如果当前的数值填入新的段,则它的贡献就是空余区间个数乘以空余区间长度乘以它自身的值。
-
不难发现这两个转移式子都和区间具体位置无关,只和区间有效长度有关。所以我们可以使用混合进制的方法来压缩状态。具体而言,我们将所有同样长度的区间归为一类,然后记录每个长度的剩余区间即可,具体见代码。
总结:
-
观察:从最难处入手
-
dp:见权值和想 dp、从转移推状态、混合进制压缩技巧
- B
错因分析:不知道最短路图。
正解:建出最短路图后跑 dfs,按照编号从小到大访问出边并维护编号之和,如果第二次访问到某个点,说明它存在两条最短路,这时的编号之和即为这个点的答案。
总结:最短路计数相关——建最短路图。
- C
错因分析:没有对式子和单调性的敏感度。
正解:
-
观察到权值的式子很像方差,展开后我们发现它正好是 \(m\) 倍方差,即 \(m \sum y_i^2 - (\sum y_i)^2\)。
-
考虑方差的结论:当 \(t\) 取平均数时,\(\sum (y_i-t)^2\)(即方差的 \(m\) 倍)取得最小值。所以问题转化为考虑在 \(t\) 的移动过程中,求 \(\sum (y_i-t)^2\) 的最小值。
-
这个 \((y_i-t)^2\) 显然就是在考查 \(y_i\) 与 \(t\) 的距离。当 \(t\) 向右移动时,选取的 \(m\) 个点显然也会向右移动,这明显具有单调性。进一步的,我们发现每个点都具有一段“存活区间”(考虑一个点的同色前驱和后继,当 \(t\) 移动的足够左,至少它的前驱会替代它,后继同理,所以是一段区间)。
-
如果我们能够求出存活区间,就可以像单调队列那样子,考虑每一个区间,然后在左端点加入某些点,在右端点删除某些点,然后动态的维护 \(\sum y_i\) 和 \(\sum y_i^2\) 即可。
-
考虑如何求出存活区间。首先我们发现 \(l_i,r_i\) 可以对称求取,所以下面只讲述 \(l_i\) 的求法。对于点 \(i\),记它的同色前驱为 \(p\),显然 \(l_i \ge \frac{x_p+x_i}{2}\)(不然 \(p\) 可以替代 \(i\));然后记 \(i\) 前面距离 \(i\) 第 \(m\) 近的点为 \(q\),显然 \(l_i \ge \frac{x_q+x_i}{2}\),这两者取 \(\max\) 就是左边界。其中 \(q\) 可以使用堆来维护。
-
求出存活区间之后,我们按照第四步的流程做即可。实现上的细节很多,包括但不限于删除标记、维护有效点个数、先加入后删除(因为要统计到所有最小值)等细节,具体见代码。
总结:
-
观察:方差结论、单调性区间。
-
代码:单调队列思想、堆维护 \(m\) 大的代码实现技巧。
- D
待补。
第二场
- A
错因分析:没有转换研究对象。
正解:
-
朴素的思路是考虑枚举每一对 \((i,j)\) 暴力计算,显然无法通过。
-
考虑转换研究对象,考虑每个质因子的贡献。
-
具体而言,对于质因子 \(p\),它能对 \(a_i+a_j\) 做出 \(\frac{p}{p-1}\) 的贡献,当且仅当 \(a_i+a_j \equiv 0 \pmod p\)。
-
这启发我们按照模 \(p\) 的余数对 \(a_i\) 分类,当 \(a_i,a_j\) 模 \(p\) 都为 \(0\),或者余数之和为 \(p\),就统计相应的贡献即可。
-
由于素因子的种类数不超过 \(\log\) 个,所以这样做是 \(O(n^2 \log n)\) 的,可以通过。
总结:
-
观察:转换研究对象。
-
题型:数论问题——考虑质因子、按照模数分类。
- B
错因分析:想到了可以找到分界点,但没有和 \(k\) 联系起来。
正解:
-
画图可知,将所有线段按照 \(a_i\) 升序排序后,我们总能找到一个分界点 \(p\),使得存在 \(y_i<d\) 且 \(y_{i+1}>d\)。
-
因为一条线段只会和 \(k\) 条线段相交,如果不相交显然答案只能在 \(y_i,y_{i+1}\) 这两条中,但现在可能相交造成扰动。由于 \(k\) 较小,我们可以直接枚举 \([i-k,i+k+1]\) 这个区间内的线段取最小值即可。
总结:
-
观察:注意题中的特殊限制。
-
技巧:粗略二分(不要求单调性的二分)。
- C
错因分析:没有想到 dp。
正解:
-
因为区间是不断扩大的,我们可以感受到可以 dp,设区间 \((l,r)\) 为当前状态。
-
考虑转移,分情况讨论,记前置状态为 \((l',r')\)。
-
对于 \(l \le l' \le r' \le r\),显然可以直接累加 \(dp_{l',r'}\)。
-
对于 \(l=l',r'<r\),可以固定右端点,对于满足 \(l \le l'' \le l'\) 的 \(dp_{l'',r}\) 进行累加。
-
对于固定左端点是同理的。
-
最后,为了保证无后效性,我们需要钦定 \((l,r)\) 为当前的最大并集,也就意味着不被 \((l,r)\) 包含的区间不能出现在它之前,于是转移系数则为 \(\frac{n!}{\prod_{i=1}^n (n-c_i) }\)(\(c_i\) 表示区间 \(i\) 包含的区间个数),dp 的时候要乘上去。
-
代码细节较多,需要维护 dp 的二维前缀和和每一个维度的前缀和,同时需要按照长度转移,但又不能直接枚举长度(因为要维护前缀和)。
总结:
-
观察:见方案数想 dp。
-
题型:dp——分类转移、考虑转移系数。
-
代码:前缀和优化、区间 dp 注意后效性问题。
- D
待补。
第三场
- A
错因分析:还是没有把发现的性质综合考虑。
正解:
-
首先观察样例,可以发现消掉能消去的东西之后剩下的一定形如某个串的平方。
-
怎么证明呢?考虑去刻画这个结构,假设消掉之后的串为 \(PWQ\)。我们钦定反转 \(W\),则 \(P\operatorname{rev}(W)Q\) 与空串等价。两边拼上 \(\operatorname{rev}(P),\operatorname{rev}(Q)\) 再消去,即得 \(\operatorname{rev}(W)\) 与 \(\operatorname{rev}(P)\operatorname{rev}(Q)\) 等价,于是 \(W\) 与 \(PQ\) 等价,代回原串即得原串与 \(PQPQ\) 等价,命题得证。
-
然后我们直接把能消去的消去,最后搞个指针维护一下就可以知道反转区间在约化串中的位置。如何映射到原串上去?因为你需要一个栈消去匹配,所以在维护栈的时候就可以顺便记录位置了。
总结:
- 观察:看样例、刻画答案。
- B
错因分析:想到了树形 dp,但没有确定转移顺序。
正解:
-
一眼树形 dp,令 \(dp_i\) 表示以 \(i\) 为根的子树的方案数。
-
如何转移?我们发现任务的安排顺序并不确定。于是我们考虑寻找一个分类标准。
-
具体而言,因为总共分配 \(n-1\) 个任务,所以总有一个人空闲,我们不妨将这个空闲者作为根。
-
根确定了,方案就确定了吗?答案是肯定的。从叶子的角度看,当叶子节点没有任务时,它不是根所以不能闲着,因此只能继承父亲的任务。继续剥去叶子,可以得到所有任务都是分配给儿子。
-
考虑优先级的影响,当儿子的优先级小于父亲,那理应儿子做任务,无需额外约束;否则,父亲就必须在儿子之前先领到任务。此时,我们便可以将原树重定向,将节点视作任务,将边视作前后的约束关系(这里是有向边,由优先级低的指向优先级高的,因为要父亲比儿子先领到任务)
-
现在我们只需要数出合法的排列数即可。这里有一个子树偏序的公式:合法排列数为 \(\frac{N!}{\prod_e s_e}\),其中 \(s_e\) 表示 \(e\) 子树大小,\(e\) 为根的孩子。可以使用数学归纳法加以证明:对于叶子节点,公式成立;设根节点的孩子的子树大小为 \(b_{1 \sim t}\),有合法排列数为 \(f = \frac{(N-1)!}{\prod_{i=1}^t b_i} \prod_{i=1}^t f_i\)(根放在第一位,然后子树内放入后 \(N-1\) 位且各自保持合法,顺序不变)
-
然后还得换根,这个好办,因为只有 \((u,v)\) 这条边转向了,所以排列数(准确的说,是排列数的分母)直接除掉一个 \(siz_u\) 再乘上 \(n-siz_u\) 即可,注意 \(siz_u\) 这里也是要跟着变的。
注意到我们用不着 dp 数组
总结:
- dp(树+方案数类型):换根法确定分类标准、根据约束建树、子树偏序公式。
- C
错因分析:没有注意到颜色的上界是 \(O(\log n)\)。
正解:
-
考虑从 \(mex\) 下手,
如果你有拉马努金般的注意力不难发现支撑颜色 \(c\) 至少需要 \(2^c\) 个节点。这个依旧可以使用数学归纳法证明:考虑颜色为 \(0\),显然需要 \(1=2^0\) 个节点;对于颜色 \(i\),它需要 \(2^{i-1}+2^{i-2}+...+2^0+1=2^i\) 个节点支撑,得证。而总点数为 \(n\),故颜色上界是 \(\log\) 级别。 -
然后考虑 dp,令 \(dp0_{u,c}\) 表示孩子全部凑齐 \(c\) 种颜色的方案数,\(dp1_{u,c}\) 表示父亲提供颜色 \(c\),孩子凑齐其余颜色的方案数。显然对于叶子,\(dp0_0=1,dp1_{1,0}=1\),答案即为 \(\sum_c dp0_{1,c}\)。
-
但是直接这样做是不行的,因为有可能子树重复提供颜色(例如儿子 1 提供了颜色 \(c\),而儿子 2 又提供了这一颜色,方案数会算重)。我们需要一个不重不漏的结构进行计数,结合颜色的上界,我们不难(?)想到状压。考虑定义 \(dp_S\) 表示当前节点提供的颜色集合为 \(S\) 的方案数。枚举父子分别的颜色 \(c,cc\) 进行转移,分两类情况:若 \(cc \neq c\),则子节点有可能自己凑好了 \(0 \sim c-1\),于是 \(dp_S\) 向 \(dp_{S {\backslash} \{c\}}\) 转移,方案数就 \(dp0_{cur,cc}\);若 \(cc>c\),则子节点有可能需要父亲的支撑,于是 \(dp_S\) 向 \(dp_S\) 转移,方案数为 \(dp1_{cur,c}\)。注意需要滚动数组辅助。
-
求出 \(dp\) 值之后,我们还需要提取相应的 \(dp0,dp1\) 以供下一次转移需要。显然 \(dp0_{cur,c}\) 等于 \(dp_{2^c-1}\),而 \(dp1_{cur,c}\) 则需要枚举缺失一种颜色的状态 \(S'\),则 \(dp1_{cur,c}=dp_{S'}\)。
总结:
-
\(mex\) 问题:状压。
-
状态设计:由辅助状态推出正式状态且互相转移、放宽限制的思想。
-
观察:注意上界、下界等。
第四场
- A
错因分析:没有想到差分技巧。
正解(以下的下标均为模 \(n\) 意义下):
-
我们不妨刻画一下题中的约束,令 \(x_i\) 表示位置 \(i\) 的操作次数,对于每个位置 \(i\),有 \(a_i=x_i+x_{i-1}+\dots+x_{i-k+1}\)。
-
考虑一下差分,得 \(a_i-a_{i-1}=x_i-x_{i-k}\),这样我们得到了对于所有 \(x_i\) 的一个约束。
-
这种差分约束显然可以赋值自由元来获得最小化。我们不妨设其中最小的 \(x_i\) 为 \(0\),然后我们可以递推出所有的 \(x_i\)。
-
现在 \(x_i\) 与 \(a_i\) 还是有差距,但可以发现每个 \(x_i\) 的差距是相等的(证明:令 \(S_i=x_i+\dots+x_{i-k+1}\),显然差值 \(D_i=a_i-S_i\),有 \(D_i-D_{i-1}=(a_i-a_{i-1})-(S_i-S_{i-1})=(a_i-a_{i-1})-(x_i-x_{i-1})=0\),即 \(D_i=D_{i-1}\);亦可感性理解,就是 \(x_i\) 与 \(a_i\) 的起伏程度一致,只需要整体平移了)
-
有了这一观察,我们就可以选取任意一个位置算出缺口,然后选择代价最小的一个环补上即可。注意一个位置会被 \(k\) 个环上的位置覆盖,而由于环的对称性,这些位置是均匀分布的。于是给某一个环加 \(1\),相当于补上了 \(\frac{k}{\gcd(n,k)}\)(环有 \(\gcd(n,k)\) 个)的数值,答案要除以这个系数。
总结:
-
思想方法:刻画约束、看到模意义下标想到环。
-
题型:差分技巧(看到序列想差分/前缀和、自由元赋值思想)、环的个数结论(proof)
- B
错因分析:想到了 kmp,但是没有观察出只有最小周期及其倍数串才会冲突。
正解:
-
首先只有加入最小周期及其倍数串才会产生重复,这个可以手玩得出。也很好理解,如果你加入一个会产生重复的串,那么它肯定具有循环节,于是自然就是最小周期的倍数了。
-
然后求方案数一定考虑 dp,但是直接做不好处理恰好 \(k-1\) 次操作的限制。显然我们可以放宽限制为处理至多 \(k-1\) 次操作,再减去小于 \(k-1\) 次操作的部分。
-
模拟操作的过程,可以发现我们每一步的操作都可以分为加周期串和加非周期串,且需要保证周期串不会连续出现。于是令 \(dp_{i,0/1}\) 表示前 \(i\) 次操作且第 \(i\) 次加/不加周期串的方案数。转移时,对于最后一次接非周期串,它可以从前一次的非周期串接上 \(S\) 或非周期串转移,或者从前一次的周期串接上非周期串转移;对于最后一次接周期串,则必须从前一次接周期串转移过来(注意这里不能包含 \(S\),因为上面已经算过)。上转移方程可以写成矩阵乘法的形式进行优化。
-
最后,我们还需要减去不合法部分。对于周期串,如果它的操作次数小于 \(k-1\),显然它可以拆分某些周期串来达成要求,因此我们只需要考虑非周期串,不合法的部分即为 \(\sum_{i=0}^{k-2} (b+1)^i\),其中 \(b\) 为非周期串个数。
-
为了回答前缀的询问,我们需要利用最长 border + 最小周期 = 字符串长度的结论,预处理 kmp 以便得到最小周期,从而得知周期串个数与非周期串个数,其中非周期串个数需要按照 \(nxt_i\) 递推求出 border 链长度再减去周期串长度,转移为 \(len_i=len_{nxt_i}+1\)。
总结:
-
题型:kmp 衍生结论(最小周期与最长 border、周期串与非周期串)、矩阵优化 dp
-
思想方法:反演思想(放宽限制)、设计 dp 的流程(模拟过程+分情况得到转移+由转移得到状态)、手玩样例。
- C
错因分析:没有想到在树上 dp。
正解:
-
这个题很反套路,一般都是把树变成区间,结果它是把区间变成树。具体而言,我们以键值对 \((i,p_i)\) 建立大根笛卡尔树,根据题中条件,我们发现题目的约束正好对应:左子树内的点可以走到根,根也可继续向右子树走,但左子树不能直接进入右子树。这与树形结构完美匹配,于是要查询某一节点的路径数量,直接从根节点往下走即可。
-
具体而言,我们可以进行函数式 dp。首先我们设计初始状态,若 \(i\) 为路径起点则 \(v_i=1\),否则为 \(0\)。接着考虑状态设计与转移,对于子树 \(T\),设其左边传来的路径数为 \(w\),则令 \(F_T(w)\) 为一次函数形式 \(k_Tw+b_T\),于是产生两种情况:左子树左边的 \(w\) 可以直接去右子树(注意它不是左子树而是左子树的左边,所以不受约束),贡献为 \(w\);同时到达根节点的贡献 \(d_u=w+S_L(w)+v_u\),因此总共传达给右子树的贡献即为 \(w+d_u\)。这样 \(S_T(w)=S_L(w)+d_u+S_R(w+d_u)\),展开可以得到根节点 \(u\) 的 \(k,b\),于是 \(k,b\) 得以维护。
-
对于交换操作,我们直接将对应子树 split 出来然后交换 rank 即可;对于查询操作,我们令 \(v_i=1\),然后查询 \(j\) 的 dp 值即可。
总结:
-
题型:函数式 dp、中序遍历树形 dp(合并子树)。
-
思想方法:序列转换为树操作、笛卡尔树对应区间 \(\max\) 约束。
第五场
- A
错因分析:没有想到单调栈维护面积。
正解:
-
从右往左加入三角形,考虑单调栈维护严格递增的右端点,对于当前三角形,不断弹出栈内右端点小于它的三角形,因为它们会被完全覆盖。
-
做完后,维护面积并的左端点 \(lt\) 为 \(\min(j,r_i)\)(\(j\) 为栈顶),则新增的面积即为 \((lt-i) \times (2 \times r_i-lt-i)\)(后面的括号即为 \(r_i-lt+r_i-i\)),自行画图理解。
总结:
- 题型:单调栈维护面积。
- B
错因分析:以为有后效性,没有考虑 dp。
正解:
-
对于那些补给点在检测点左边的点对,我们可以直接一路向右移动,所以可以将其删除,不予考虑。
-
现在只有那些补给点在检测点右边的情况了。此时考虑 dp,令 \(dp_i\) 表示已经处理完前 \(i\) 个检测点的最小移动距离。
-
考虑转移,思考最优策略是什么。显然我们可以从 \(i\) 向右走到最远的补给点,拿上这一路的补给,然后向左折返到最远的未检测点,然后一直做完到 \(i\) 的检测。这部分就是 \(dp_i = \min_{j=1}^{i-1} \{dp_j+b_{v_i}-a_{v_j}+b_{v_i}-a_{v_{j+1}}+a_{v_i}-a_{v_{j+1}}\}\),其中 \(v_i\) 是删除之后的下标数组。
-
然后考虑答案,因为我们要走到全局最右端(别忘了我们还有删除的点对要处理),所以可以选择做完 dp 后直接走到最后,或者在某个中间状态走到最后然后折返。于是 \(ans=\min(dp_m+\max(a_n,b_n)-a_{v_m},\min_{i=0}^{m-1}\{dp_i+2 \times \max(a_n,b_n)-a_{v_i}-a_{v_{i+1}}\})\)。
-
但是这东西会超时,所以考虑优化,容易发现和 \(i\) 有关的项都可以提出来,然后里面维护一个关于 \(j\) 的式子的最小值即可,用一个变量 \(mn\) 维护。
-
最后注意一下初始状态,\(ans\) 的初始状态是考虑从 \(0\) 出发走到最右端,然后回到 \(1\),即 \(\max(a_n,b_n)-a_{v_1}\),而 \(mn\) 的初始状态由转移方程可得 \(mn=dp_0-a_{v_0}-2 \times a_{v_1}=-2 \times a_{v_1}\)。
总结:
- 题型:移动类 dp——钦定两个顺序(先后顺序、转移顺序),考虑最优策略。
- C
错因分析:没有想到从后往前填。
正解:
-
要求字典序最小,从前往后处理显然局部最优并不能导出全局最优,只能从后往前加入后缀。每加入一个字符串,我们就枚举它的后缀,考虑加到答案的前面去,取字典序最小的那个。
-
现在问题在于如何比较出两个后缀哪个更优,可以二分 LCP 长度,然后用哈希 check 即可。
-
实现上有一点巧思,我们可以倒着求哈希值,然后维护一个指针指向上一次填到的位置的前一个,每次二分求出 LCP 长度之后就将指针更新为最优的起始位置,下次拼后缀的时候就可以顺便把这段前缀覆盖掉。具体见代码。
总结:
- 题型:字典序最小化——从后往前考虑、二分+哈希比较。
- D
错因分析:考场上根本没看。
正解:
-
看到子集求和,考虑往期望的方面思考。我们可以计算出每个预案的期望,最后乘以 \(2^Q\)。
-
考虑拆开区间平方和,发现我们可以枚举 \((i,j)\) 然后计算每个 \(a_i \times a_j\) 出现的次数再全部相加。显然一个区间 \([i,j]\) 被选中的次数就是 \(\min(i,j) \times (n-\max(i,j)+1)\)。然后考虑拆位,每一对位 \((p,q)\) 的贡献就是它们同时为 \(1\) 的概率乘上 \(2^{p+q}\)。总之,要求得期望,我们只差概率没有算出来了。
-
那么如何求得概率?不难想到分类讨论。对于两个位 \((p,q)\),显然有三种情况:\(i,j\) 都没有被翻转、\(i,j\) 有且仅有一位被翻转、\(i,j\) 都被翻转。对于第一种,概率显然取决于 \((i,j)\) 本来的位,要么是 0 要么是 1;对于第二种,概率为 \(\frac{1}{2}\),当且仅当不翻转的那一位为 \(1\),否则概率为 \(0\);对于第三种,显然概率为 \(\frac{1}{4}\)。
-
此时,我们尚未找出分类的依据,即 \((i,j)\) 到底谁被翻转。我们发现 \(Q\) 次修改的信息完全没用上,显然可以通过一维差分维护翻一位的区间、二维差分维护翻两位的区间,然后累加时直接得到三种情况的翻转次数即可。注意只翻转一位的要减掉翻转两位的去重。
总结:
-
题型:子集求和——转化为期望问题、分类讨论求概率。
-
思想方法:见式子拆式子(乘积拆成求和)、见二进制拆位。
第六场
- A
错因分析:没有按位考虑。
正解:
-
显然对于一个位置 \(i\),显然限制它的是 \(\min\{c_i\}\),记它为 \(b_i\)。但这个 \(p_i \le b_i\) 这个约束并不是充分的,因为有的集合根本取不到它。于是,某个位置的 \(p_i\) 想要成为真正的最大值,必须出现在所有满足 \(b_x=c_i\) 的集合中。
-
记 \(num_v\) 表示要求最大值为 \(v\) 的集合数,我们可以扫描所有集合,对于每个 \(b_x\) 统计 \(b_x=c_i\) 的次数,若它与 \(num_v\) 相等,则可以加入最大值的候选点中。记值为 \(v\) 的候选点数量为 \(cnt_v\)。
-
从填数的角度考虑,越大的数它的限制将会越紧,因此我们考虑从大到小填数。维护 \(avail\) 表示可用数量,每次循环开始加上当前的 \(cnt_i\),然后如果在某个集合中就竞争最大值,方案数为 \(cnt_i\),否则方案数为 \(avail\),注意 \(avail\) 最后要减一以及判掉非法情况。
总结:
-
题型:序列方案数问题——按顺序填数(从约束紧的开始)。
-
思想方法:刻画约束。
- B
错因分析:没有倒着考虑。
正解:
-
当你尝试模拟玩家行走的过程,你会发现这很难做,原因在于树并不总是连通的。因此我们正难则反,考虑只剩下一种颜色 \(c\) 的情况。此时其他的非 \(c\) 边全部开放,这意味着删除所有颜色为 \(c\) 的边之后,树就是连通的。这是一个很好的性质,换言之,我们从最终状态走到初始状态的过程中树总是连通。
-
这让我们考虑建模,不难发现通过将同颜色的点形成的连通块缩成一个点,我们可以得到一个 DAG。有了 DAG,自然想到拓扑排序,将玩家的轨迹记录下来。
-
于是,考虑一个连通块什么时候会插入队列。我们不妨定义 \(b_i\) 表示颜色为 \(i\) 的连通块的边界点个数,\(k_i\) 表示颜色为 \(i\) 的连通块个数,显然它需要有至少一个边界点来和其他连通块相连,于是 \(b_i \ge k_i\);同时它也至多有一个边界点,不然它就会被夹在中间。因此我们得到当且仅当 \(b_i=k_i\),颜色为 \(i\) 的连通块会被插入队列。但是孤点不满足这一条件,但是它也得插入,所以整合一下可以得到条件为 \(b_i \le k_i\)(这个虽然看起来很不对,但是仔细想一下可以发现确实没有多加)。
-
然后考虑怎么记录玩家的轨迹,常用的套路就是记录前驱节点然后递归转移,这个题同理。但是请注意:第一,你需要维护 \(d_i\) 表示邻居的颜色种类数,以及 \(z_i\) 表示邻居的颜色集合来处理新加入的队列元素;第二,要区分拓扑排序和玩家的路径是有区别的,拓扑排序可以一次剥离多个颜色连通块,但是玩家只有一个,所以记录前驱的时候当 \(k,b=1\) 时前驱为边界点,\(k=1,b=0\) 时前驱为 \(0\),否则没有前驱,而不能把所有 \(b=k\) 的都设前驱为边界点了。
总结:
-
题型:缩点(见同类缩点) + topo(见 DAG 想 topo)。
-
思想方法:正难则反、合并条件(相信你的直觉)。
第七场
- A
错因分析:没有想到反着做。
正解:直接按照优先值按秩合并即可(即优先级小的在上)。
总结:
- 思想方法:正难则反(尤其是有删除操作时必用)。
- C
错因分析:完成了第一步转化,但是没有维护支配对。
正解:
-
容易发现合法区间就是逆序对权值之和的最大值小于等于 \(k\) 即可。
-
于是考虑对于一个位置 \(i\),我们发现只需要考虑离 \(i\) 最近的权值严格大于 \(i\) 的位置 \(p_i\)(因为是逆序对所以权值肯定大于 \(i\) 且在 \(i\) 之前,同时因为是存在性问题所以考虑最近的即可)。可以使用单调栈维护 \(p_i\),每次将 \(w_i+w_{p_i}\) 单点修改在 \(p_i\) 上,然后查询 \([l,r]\) 的最大值即可。
总结:
1.思想方法: 支配对思想(常用于二维数点)
第八场
- A
错因分析:没有对序列进行变换。
正解:
-
在模 \(3\) 的意义下,R,G,B 对应着 \(0,1,2\),于是 \(f(a,b) \equiv -a-b \pmod 3\)。
-
考虑差分,设相邻的三个数依次为 \(a,b,c\),则差分可得 \(b-a,c-b\),操作之后差分是 \(a+c-b-a=c-b,c-(a+c-b)=b-a\),可见操作相当于交换差分数组的相邻两项。
-
于是求出初始差分数组和最终差分数组,然后将最终的按照初始的顺序标号,最后求一遍逆序对个数即可。
-
无解的情况就是差分数组元素不能一一对应或者第一个元素不同(显然第一个元素和差分数组确定之后最后一个元素就确定了,因此无需考虑最后一个元素)。
总结:
- 题型:序列操作——将字符转化为模意义下的数值、差分或前缀和简化
- B
错因分析:没有刻画约束,转化为保序回归问题。
正解:
-
考虑刻画约束,发现题目想要表达的意思就是相隔 \(p\) 的两个 \(0\) 之间要夹着 \(q\) 个 \(1\)。设 \(b_i\) 表示第 \(i\) 个 \(0\) 前面有多少个 \(1\)(注意这里的 \(i\) 是 \(0\) 的下标,而非真实的数组下标),故约束可以量化为 \(b_i+q \le b_{i+p-q}\)。
-
这个下标看上去很复杂,我们考虑将下标模 \(p-q\) 同余的位置归为同余类,原不等式化为 \(b_i+q \le b_{i+1}\)
-
考虑去掉偏移量,令 \(b_i'=b_i-(i-1)q\)(从下标之差可以得出 \(i-1\),然后为了消去 \(q\) 所以乘上 \(q\)),则原不等式化为 \(b_i'+iq \le b_{i+1}'+iq \Rightarrow b_i' \le b_{i+1}'\),这便得到了一个标准的 \(L_1\) 保序回归模型,使用整体二分解决即可。最后求出的答案可以直接按原数组下标拼接,因为同余类位置不会互相交错。
总结:
-
题型:\(L_1\) 保序回归模型——整体二分(寻找最小前缀和作为分界点,左边赋值 \(mid\),右边 \(mid+1\),分治值域求解)
-
思想方法:刻画约束(本题使用前缀和形式)、归为同余类(简化下标)、配凑去除偏移量(利用下标关系)。
第九场
- A
错因分析:没有刻画覆甲使用的区间。
正解:
-
容易发现金属化是固定的,所以而覆甲的贡献形成一段区间(即使用周期的区间)。
-
考虑刻画这个区间,肯定先得求出 \(l,r\)。假设我们购买了一次覆甲,则它的最长使用周期就是 \(b_i\)(你需要至少买到伤害这么多点的覆甲)。记 \(h_i=\max_{j \le i} \{a_j+b_j\}\)(即覆甲最远能够到的时间点),则 \(l_i=\max(0,h_{i-1}-a_i),r_i=b_i\)。
-
现在加入金属化等级 \(m\) 进行考虑,考虑量化贡献。运用函数分析,设 \(F(m)=xm+ y \sum_{k \ge m} C(k)\)(其中 \(\sum_{k \ge m} C(k)\) 就是比 \(m\) 大的数的个数,整个式子就是金属化的贡献加上覆甲的贡献)。在 \([l_i,r_i)\) 上(\(r_i\) 取不到是因为取到了就是全用金属化了),由于 \(C(k)\) 是常数(注意不一定是 \(1\),因为可能一个坐标上有多个事件),所以这是个一次函数,只会在端点处取得最值。
-
这启发我们自下而上进行扫描线,从端点 \(p\) 转移到 \(q\) 需要做一个差分,可得 \(F(q)=F(p)+(q-p) (x-yC)\),初始 \(F(0)=y\sum (r_i-l_i)\)(全用覆甲)。然后 \(C\) 的维护是套路的,就是左端点 \(+1\) 右端点 \(-1\) 即可。注意一下重复区间的情况,还有无效区间的剔除。
总结:
- 题型:
区间问题——刻画 \(l,r\)
端点问题(一类特殊的区间问题)——扫描线+差分转移
贡献问题——量化贡献,函数分析(分析单调性和最值)
第十场
- A
错因分析:想到了可以求出元区间然后合并,但是没有刻画出元区间。
正解:
-
有一个很显然的想法:我们将所有基本区间求出来之后,如果区间数量不超过 \(k\) 自然就是答案,否则按照间隔从小到大合并即可。
-
考虑这样的基本区间是什么,我们发现它需要满足内部排序后能直接嵌入,这表明区间最小值应不小于左侧最大值,区间最大值不大于右侧最小值。而又要满足最小,考虑刻画端点,求出所有满足 \(\max_{1 \sim i} \le \min_{i+1 \sim n}\) 的 \(i\),这些相邻的 \(i\) 构成的区间就是元区间。
总结:
- 题型:区间问题——刻画端点。
- B
错因分析:没有试图刻画结构,对数据范围不敏感。
正解:
-
首先看到 \(n \le 150\) 可以想到大概是 3 次方或者 4 次方的复杂度,可能是 floyd 或区间 dp,但是这题显然与图论无关,所以考虑区间 dp。
-
那么我们就需要去刻画区间的结构,区间 dp 需要把两个子区间合并,因此我们需要分界点。但这题的分界点并不能随便枚举,因为你无法保证左右区间都在之前轮中被处理。结合题目的约束,我们发现可以将区间最大值的位置作为分界点,显然其他位置都会在他之前被处理。考虑固定最大值然后计数。
-
我们需要在状态中知道区间端点和轮数,还需要钦定某个状态,于是不难定义 \(dp_{l,r,t}\) 表示区间 \([l,r]\) 恰好在第 \(t\) 轮删空的方案数,但是这个并不好直接转移。考虑反演思想,设计辅助状态 \(f_{l,r,t}\) 表示区间 \([l,r]\) 前 \(t\) 轮删空的方案数。这样,\(f\) 可以由 \(dp\) 数组前缀和得到,然后 \(dp\) 的转移就是对 \(S_{l,m,t-1}S_{m,r,t-1}-S_{l,m,t-2}S_{m,r,t-2}\) 求和(因为是恰好所以减掉 \(t-2\) 的贡献),系数为 \({r-l-2 \choose m-l-1}\)(去掉头尾和 \(m\),选出 \(m-l-1\) 个数放左边)
-
但是因为我们钦定 \(dp\) 和 \(f\) 都是删空,所以无法直接表示整个区间,考虑设计另外的状态。我们发现对于整个区间其实也是枚举最大值分割,画一下发现是由一段前缀和一段后缀加上一个元素组成,于是设计 \(L_i\) 表示前 \(i\) 个数且最大值在 \(i\) 的方案数,转移还是枚举 \([1,i]\) 的最大值 \(j\),可以发现 \([j+1,i-1]\) 的数都会被删,所以贡献为 \(S_{j,i,i-j-1}\)(\(i-j-1\) 就是保证全部删空),直接从 \(L_j\) 转移,系数为 \(i-2 \choose j-1\)。\(R_i\) 同理。最后答案就是 \(\sum_{i=1}^n {n-1 \choose i-1} L_i R_i\)。
-
最后初始状态提一下:\(S_{l,l+1,0}=1\)(空区间),\(L_i=1\) 当且仅当 \(a_i=-1\) 或 \(a_i=0\),\(R_i\) 同理。注意 \(t<2\) 时令 \(S_{l,r,t-2}=0\) 即可。
总结:
-
区间 dp 问题——刻画结构
-
计数 dp——转移=从什么转移+组合系数
思想方法:
-
反演思想(在状态设计上的应用)
-
对数据范围敏感(\(n^3\) 只有区间 dp 或 floyd)
浙公网安备 33010602011771号