26DMYCSP-S#10

Daimayuan CSP-S 2026 Round 10

闲话

起得比较晚,这场是 \(9:00\) 开的。

感觉是超级挂分大战,T2T3 的样例有和没有一样。明明是 weak pretest 组成的怪物,在我眼中却是美丽的少女。

10min 看了四个题,T1 是常规的计数,T2 是一些树上结论相关的传统题,注意到 \(n \leq 10^6\) 大概率是直接得出结论然后线性维护/并查集维护这类的。T3 是对一些连续子段的权值计数的问题,这种东西为啥要取模,有点诡异。T4 看上去是 Dilworth 状物。都是比较常规的题,一眼看不出有哪个题好做,于是顺着做。

先开 T1,本质是按照位置分为每个等价类,每个等价类有一类值域上的 \(\leq\) 约束,可以直接分层填数,有点难写大概 40min。

开 T2,所有的钥匙按照环的标号分为若干等价类,然后你考虑定根后如何判定,此时可以直接对等价类标号建图,按拓扑序填,一旦有环则无解。进一步地你注意到答案必定是连通块,因此可以考虑倒推,每次删掉一个可以删掉的等价类及其对应的所有约束,这个可以直接线性,大概 1h15min。这个做法貌似比写虚树的做法细节少很多,相对不容易挂分,复杂度还能少个 \(\log\)。

开 T3,细细玩了一下发现答案的取值确实很大但没有到常规计数那么大,更像是对一个最优化的框架出的,只是换了一个统计量。那么考虑拆贡献,注意到如果当前集合内的元素在值域上构成一个连续前缀,就可以类似多重背包,二进制拆分可以直接分析每个位对当前区间对应的 \(\text{mex}\) 的贡献。所以换成枚举每一位然后看这层能贡献的端点对 \((l,r)\) 的数量。因为 \(\text{mex}\) 随集合大小增大单调不降,所以可以直接做到线性,总时间复杂度是 \(\mathcal{O}(n \log V)\) 的,这个相对好写花了 1h35min 左右。

最后没多少时间了,写了个 T4 的记忆化搜索 + 特殊部分 A + 假贪心,注意到它过了所有大样例,这很诡异,希望能多搞点分回来。

出分之后发现 T3 端点对的部分不能取模需要存原值,所以挂了 \(30\),T4 只拿到对应的低保分,还是没能做到。其实要是早看看 T4 可能分会高一些的,但是谁知道呢,这种题特征太不明显了感觉难以通过策略层面上改动什么地方从而有意识地注意到这个题,\(100 + 100 + 70 + 25 = 295\),rk 9。

这场是没有造 gen.cpp 的,以后看来不能因为代码源样例多就不去对拍了,策略需要对应调整一下,后几场看看是一题一题对拍还是最后留时间对拍比较好。


T1

tag:组合计数。

对每个位置 \(p_i\),找出所有包含 \(p_i\) 的约束,令这些约束对应 \(c_j\) 最小值为 \(w_i\),初始为 \(n\),则必定有 \(p_i \leq w_i\)。

然后考虑每次取出最大值 \(x\),这个最大值必定同时包含于所有 \(c_i = x\) 的集合,并且必须有 \(w_i = x\)。前者确保了所有集合恰取到这个最大值,后者保证不会出现一个上界约束更小的集合被这个位置影响。

因此可以求出 \(t_x\) 表示以 \(x\) 为最大值的约束数量,并数有多少个位置满足 \(w_i = c_j\),如果满足条件的位置数量恰好等于 \(t_x \neq 0\),这个取值就可以填在这个位置上。可以由此求出 \(q_i\) 表示 \(i\) 这个值可以被填进去的位置数。

那么可以从小到大填数,维护当前总有效位置数 \(m\) 和当前这一层的 \(q_i\),如果当前取值没有对应的约束,它有 \(m\) 种填法,否则它有 \(q_i\) 种填法。两种情形都会令总有效位置数少 \(1\)。这样即可做到时间复杂度 \(\mathcal{O}(n)\)。

ac link


T2

tag:贪心、图论、可达性分析、Ad-hoc。

考虑定起点为根,对于一条祖先链 \(u \to v \to w\),必定是先操作 \(c_{(u,v)}\) 再操作 \(c_{(v,w)}\),所以可以直接对颜色的先后顺序建图,只需要判定是否为 DAG 即可确定当前点为根是否可行。时间复杂度 \(\mathcal{O}(n^2)\)。

然后考虑换一个角度,倒退整个操作过程,假设最后使用的颜色是 \(c\) 然后逐步检验能否到达这个状态,如果能还原出整棵树那么就是合法的。在使用 \(c\) 之前所有颜色非 \(c\) 的边都已经打开,并且必定能相互到达,因此删去所有 \(c\) 颜色边之后,剩余的边必定位于同一个连通块内。那么可以找出所有连边同色的极大连通块,上面的约束等价于对每个颜色 \(c\) 的连通块,至多有一个点连接了其他颜色的边。这是因为如果有一个块至少有 \(2\) 个这样的点,删除这个块内所有连边之后这两个点必定是不可达的,否则与极大连通块和树的限制矛盾了。由此当且仅当每个全 \(c\) 边的连通块均为树上的叶子连通块才是合法的。由此所有的起点就是删到只剩下一种颜色时的连通块内的点,这个可以直接倒序维护。

所以现在只需要维护这个删点的过程了。对每个颜色你注意到上面条件等价于对边数 \(e_c\),端点集合 \(v_c\) 以及连通块数 \(k_c\) 有 \(k_c + e_c = |v_c|\)。然后每次删一个块对应的 \(e_c,v_c\) 增量都是相同的故 \(k_c\) 不变。则可以把颜色意义下的邻域大小求出来,设为 \(d_c\),如果 \(d_c = k_c\) 就代表这个颜色可以删除了。由此可以直接 BFS 对应的状态,微扰可以证明如果有解,这样每次任意扩展一步删一个颜色肯定是可以找到一组可行解的。

因为每个点对应的邻域只会在它被删去的时候产生贡献,所以这个过程中所有修改都是 \(\mathcal{O}(n)\) 的,总时间复杂度 \(\mathcal{O}(n+m)\)。

ac link


T3

tag:位运算、双指针、单调队列。

对于单个区间研究权值,将所有区间内元素拍到值域上,设 \(v\) 为从 \(0\) 开始,可以连续凑出的极长值域前缀的右端点,从 \(v = 1\) 开始,如果当前的数 \(x\) 有 \(\leq v\),那么可以令 \(v \to v + x\),否则答案就是 \(v\)。

因为有多种凑出一个数的方法,考虑定一个“极小”的转移,换言之就是当前值域内唯一的转移。注意到 \(v \to v + x \to v + x + y\) 当且仅当 \(x \geq v\) 并且 \(y \geq (x + v)\) 才能保证这个转移是当前值域内唯一的。由此,考虑将所有前缀内的数按照 \([1,2),[2,4),\dots,[2^k,2^{k+1})\) 分段,同一组内的数,要么全部被上述贪心纳入 \(\leq v\) 的转移,要么不存在任意一个数被纳入转移。这个道理很简单就是取出最小值 \(t\),如果被纳入那么此时 \(v \geq t\),所以 \(v + t \geq 2t \geq 2^{k + 1} - 1\)。因此此时剩下的数都可以被纳入。

因此只需要找到 \(c_{[l,r],j}\) 表示区间 \(a_{[l,r]}\) 内,位于 \([2^j,2^{j+1})\) 值域内的元素和,然后我们一层层加入所有的数,初始 \(v = 1\),如果进行到某一个 \(j\) 满足 \(2^j \leq \max\limits_{l \leq i \leq r} a_i\),此时 \(v \geq 2^{j}\) 那么可以加上对应的 \(c_{[l,r,j]}\)。因此可以换维:考虑整体枚举每一位,找出所有用 \(2^j\) 以下的所有数可以凑出 \(v \geq 2^j\) 的区间,这个区间数量就是 \(2^{j}\) 这一位对应的系数,然后统计这些区间对应的 \(c_{l,r,j}\) 之和递推到下一位。

这个我们可以扫描线处理,从左到右枚举右端点 \(r = 1, 2, 3, \dots, n\),根据 \(\text{mex}\) 不降的性质可以确定可行的左端点必定是一个长度单调不降的前缀。所以只需要对每个 \(r\) 求出最右侧的 \(l\) 使得 \([l,r]\) 对应的最大取值 \(v_{[l,r]} \geq 2^j\)。设这个最大左端点为 \(f_i\),初始时每个位置有 \(f_i = i\),现在要做的是在线性时间复杂度内从 \(j\) 的 \(f\) 递推到 \(j + 1\) 的 \(f\)。这个相对而言就简单一些,只需要对每个区间 \([l,r]\) 维护小于 \(2^j\) 的所有数之和,以及所有属于 \([2^j,2^{j+1})\) 的区间内的数的最小值。记第一个数 \(s\),第二个数 \(v\),那么 \([l,r]\) 能凑出 \(2^{j+1}\) 及以上的数等价于 \(f_r \geq l\) 并且 \(s + 1 \geq v\)。

因此可以直接双指针维护 \([l,r]\),对 \(s\) 直接在移动左右边界的时候单点加减,对 \(v\) 直接用单调队列维护。这样我们统计出每个 \(r\) 对应的 \(l\) 的数量,设 \(S_{i,j}\) 表示前 \(i\) 个元素中属于 \([2^j,2^{j+1})\) 的元素之和,则这一层每一个 \(r\) 对应的总贡献就是 \(\sum_{l=1}^{f^{j+1}_r} c_{[l,r],j} = f^{j+1}_r \times S_{r,j} - \sum_{i=0}^{f^{j+1}_r-1} S_{i,j}\),其中 \(f_{p}^{j}\) 表示 \([2^{j},2^{j+1})\) 意义下的 \(f_p\)。对每层这样统计是 \(\mathcal{O}(n)\) 的,总时间复杂度就是 \(\mathcal{O}(n \log V)\)。又因为 \(s\) 需要保存原值,最大时会到 \(5 \times 10^{23}\),所以需要用 __int128_t 而不能用 long long。

ac link


T4

tag:Dilworth 定理、二分图、Hall 定理、贪心、DP。

考虑用连边刻画出链划分的依据:对 \(i \lt j, p_i \lt p_j\) 的点对 \((i,j)\) 连一条边。那么合法的链就是大小 \(\geq 2\) 的团,沿着下标递增的顺序必定可以将这样的团拆成若干个大小恰为 \(2\) 的团和至多一个三元环。

这个类似于找割的过程可以等效到找独立集的过程,所以我们考虑 Hall 定理:对一个点集 \(S\),其邻域 \(N(S)\) 表示所有点集中节点的邻域的并。独立集是所有满足 \(S \neq \varnothing, S \cap N(S) = \varnothing\) 的集合,那么一个序列可以分组当且仅当对每个非空独立集 \(S\) 均有 \(|N(S)| \geq |S|\)。

必要性就是 Dilworth 定理,因为每个合法链中至多包含一个 \(S\) 内的点,而且这个点需要一个同组的节点,不同组的节点必定不同,所以必定至少需要有 \(|S|\) 个邻域内的点。

充分性就是,一个点拆成入点和出点,一条边 \((u,v)\) 对应 \(u_L \to v_R\) 和 \(v_L \to u_R\),这个是二分图,如果某个左部点中的点集 \(X\) 不满足 Hall 定理,即 \(|N(X)| \lt |X|\),令 \(S=X \setminus N(X)\)。\(S\) 内没有边,否则这条边的端点也属于 \(N(X)\)。此外,\(N(S) \subseteq N(X) \setminus X\):邻点属于 \(N(X)\);若它同时属于 \(X\),就会使相邻的 \(S\) 中的点属于 \(N(X)\)。于是 \(|S| - |N(S)| \geq |X \setminus N(X)| - |N(x) \setminus X| = |X| - |N(X)| \gt 0\),与判据矛盾。因此二分图存在完美匹配。

这个完美匹配对应的是原序列中一个没有 \(p_i = i\) 的置换。因此对偶环可以直接分解为若干个大小为 \(2\) 的环,对奇环可以按照编号从小到大定序,奇环上不可能每个点的两个度数都是入度或都是出度,因此一定存在至少一个 \(u \to v \to w\) 状物,这三个东西拆出来成为单独的满足传递性的三元组,剩下的两两配对成大小为 \(2\) 的小环即可。

有了这个结论,可以确定对非空独立集 \(S\),需要 \(|N(S)| - |S| + 1\) 次删除操作才能使序列符合要求,无法被分组。因此答案就是 \(\max\left\{0,1 + \min\limits_{S \neq \varnothing} \left(|N(S)| - |S|\right)\right\}\)。可以考虑 DP,每次处理当前严格 LDS 的最后一项,令 \(L_i\) 表示所有 \(1 \leq j \lt i, p_j \lt p_i\) 的 \(j\) 的数量,同理有 \(R_i\)。设一个 LDS 中相邻两个位置 \(i,j\),则有 \(i \lt j, p_i \gt p_j\),对 \(i \lt x \lt j\) 它属于邻域当且仅当 \(p_x \gt p_i\) 或 \(p_x \lt p_j\)。又因为 \(p_i \gt p_j\) 所以这两个情况是互斥的,令 \(c_{[l,r]}\) 表示这样的 \(x\) 对 \(i = l, j = r\) 的数量,\(f_i\) 表示所有以 \(j\) 结尾的 LDS 划分中,\(|N(S) \cap [1,j]| - |S|\) 的最小值,则有 \(f_i = \min\left\{L_i - 1, \min\limits_{i \lt j} \left(f_i + c_{[i,j]} - 1\right)\right\}\),然后求出每个 \(f\) 之后和对应的 \(R\) 合并即可得到答案。这样直接做是 \(\mathcal{O}(n^3)\) 的。

然后你注意到因为 LDS 是有传递性的,所以 \(c\) 有支配关系,可以对当前 \(i\) 分讨是立刻贡献还是等最近的满足偏序关系的 \(j\) 再贡献,对后者可以将其转移到对应左侧最近的左端点上。具体来说就是对每个 \(j\) 可以直接对所有 \(i \lt j\) 维护 \(g_i\) 表示所有 \(x \in [i + 1, j - 1]\) 的数量,同理可以对所有 \(i\) 维护 \(h_j\) 表示所有 \(x \in [i + 1, j - 1]\) 的数量,那么当扫到位置 \(i\) 时,对一个 \(j\),当且仅当 \(p_i \gt p_j\) 可以转移,那么 \(c_{[i,j]} \leftarrow g_i + h_j\),并且 \(g_i\) 无需更新。如果 \(p_i \lt p_j\) 那么不需要更新 \(f\),此时将 \(i\) 对应贡献计入 \(h_j\) 即可。具体来说就是 \(h_j \leftarrow h_j + 1\) 并且 \(g_i \leftarrow g_i + 1\)。额外需要考虑的是 \(h_j = L_j\) 的情况,单独转移即可。

最后求出所有 \(f,g\) 之后只需要合并两者得到答案为 \(\max\left\{ 0, \min\limits_{1 \leq j \leq n} \left(f_i + g_j + 1\right) \right\}\)。时间复杂度 \(\mathcal{O}(n^2)\)。

ac link


posted @ 2026-09-27 19:21  Twistedmind  阅读(10)  评论(0)    收藏  举报