26DMYCSP-S#9
Daimayuan CSP-S 2026 Round 9
闲话
回来了,都回来了,曾经的代码源回来了。继上场 Div.1 的 T2 猎奇题之后,这场又出现了 T1 蓝 T2 黑 T3 喵了个喵的情况。
20min 看了四个题,T1 像是线性的贪心分讨题,T2 不像啥简单东西,可能不难但大概率比较复杂。T3 像是偏分析操作的构造(伏笔),T4 是非人类题。
先开 T1,考虑逐位贪心,不难注意到其中一个串选择整串是不劣的,另一个要考虑是否有前导 \(0\) 的问题,再分析去掉前导 \(0\) 之后是否是全 \(1\) 串,就做完了,30min 左右。
然后看 T2,能想到差分之后问题变为每个取值卡在一段区间里面,然后要总数最大状物,那么首都可以直接由差分序列的最小值确定了,然后不会了。
开 T3,一眼看上去 \(f(n)\) 的取值是并不显然的,打表观察,考虑尽可能增大编辑距离的方法是正交的操作要尽可能多,一个构造是全 \(0\) 或全 \(1\) 串变换到 \(0/1\) 交替,因此有 \(f(n) \geq \lceil n / 2 \rceil\)。然后我们需要构造证明这个东西是对的,因为判定量都是 local 的,与此同时 \(f(n)\) 也可以被均摊进实际有效的作用位置,自然想到归纳构造。对 \(n = 9, 10\) 有 \(5\) 步的构造,那么可以在维持 \(f(n)\) 最小的情况下一直做 \(n \to n - 10\),最后可能剩下至多 \(18\) 位,因为是任意的 \(|S| \leq 18\) 变换到 \(|T| \leq 18\),所以这个难以手玩,考虑爆搜,一方面肯定可以 meet in the middle,另一方面注意到连边对应一个 DFA,那么做可行性剪枝,预处理出极小的转移边避开等价转移,还可以更快。大概用了 2h45min。
最后回来看 T2,注意到可以对每个点的限额贪心调整,那么问题变成了有 \(m\) 对 \((1,-1)\),你要贪心匹配使得路径总权值尽可能大,没啥时间了所以无法想正解,写了个双指针 \(\mathcal{O}(nq)\) 就交了。
最后是 \(100 + 60 + 100 + 0 = 260\),rk 13,没挂分是好事,但存在两方面的问题,一是乱搞能力太差了,很多时候花 10min 直接跑会比硬推性价比高很多。二是对数据结构维护贪心的理解还不够深刻,因为 T2 正解其实和双指针差别不大的,想到对的模型之后直接想到动态维护前 \(k\) 大,树状数组上二分维护匹配也能写出正解。
T1
tag:贪心,位运算。
因为只有两个串所以直接逐位贪心,位数最大肯定是对的,并且不会有任意一个子串的取值超过 \(S\) 本身,因此我们固定 \(S_1 = S\),然后此时如果 \(S\) 全 \(0\) 或者全 \(1\) 另一个串直接确定了,否则 \(S_2\) 肯定尽可能先把前导 \(0\) 后面第一段 \(0\) 补上,然后再考虑能不能补第二段、第三段...
然后因为补上第一段 \(0\) 之后如果为了补第二段导致中间的第二段 \(1\) 被影响,那肯定是不优的。设前导 \(0\) 后第一段 \(1\) 共有 \(x\) 个,紧随其后有 \(y\) 个 \(0\),那么 \(S_2\) 的选择必定是在 \(S_1\) 的第一段 \(1\) 中选取后 \(\min(x,y)\) 个位置,因为只有这样能让前 \(x + y\) 位均为 \(1\),并且第 \(x + y + 1\) 位不受影响,多 \(1\) 会导致答案第 \(x + y + 1\) 位被置为 \(0\),少 \(1\) 则第 \(x + y\) 位留着还是 \(0\),显然都不优。
则可以直接求这两段的长度,时间复杂度 \(\mathcal{O}(n)\)。
T2
tag:树状数组,线段树,贪心,扫描线,线性规划。
这题真不简单吧。
令每个点对应的距离标号为 \(d_i\),那么一段路径等价于给 \(x_i\) 的系数 \(+1\),给 \(y_i\) 的系数 \(-1\),记这个系数为 \(c_i\),那么问题等价于确保 \(|d_i - d_{i + 1}| \leq L_i\) 的基础上,使得 \(\sum_{i=1}^{n} c_i \times d_i\) 最大化。
因为 \(\sum c_i = 0\) 所以不用考虑 \(d_i \geq 0\) 的限制,因为可以对着最小值整体取反,使得恰有一个位置(最小值对应位置)为 \(0\) 并且其余位置非负。
那么你考虑差分,令 \(d_0 = 0, x_i = d_{i+1} - d_i\),原来的限制就是 \(|x_i| \leq L_i\) 并且 \(\sum x_i = 0\)。然后要使得 \(d\) 最大就等价于对差分序列 \(x\),找到一组分配方案,使得每个位置 \(\times (n - i + 1)\) 之后的总价值最大,且满足前面的条件。
因此可以直接将每个位置按照这个被遍历到的次数从小到大排序,必定是存在一个分界点,左边全部取到 \(-L_i\),右边全部取到 \(L_i\),分界点是容易证明的,考虑设三段然后调整。全部取到极值也是易证的,可以注意到对一个更小的系数,调整至 \(L_i\) 相对应的后面系数更大的收益会更多。
因此可以直接用树状数组维护 \(\sum L_i\) 然后每次二分出对应的分界点。时间复杂度 \(\mathcal{O}((n + q) \log n)\)。
T3
tag:构造,启发式优化,Ad-hoc。
注意到 \(f(n)\) 是一个类似于常规贪心题的统计量,所以需要先打表找规律,研究 \(f(n)\) 是啥,然后考虑对应的构造。
经过打表发现 \(n \in [4,8]\) 时分别有 \(f(n) = 6, 4, 5, 5, 5\),然后从 \(n = 9\) 开始就有 \(f(n) \geq \lceil n / 2 \rceil\)。在串两侧补上 \(0\),定义 \(W(S) = \sum_{i=0}^{n} [S_i \neq S_{i + 1}]\),翻转区间 \([l,r]\) 时内部相邻字符的差异不变,所以只有边界处会改变,故每次操作至多令 \(W(S)\) 增加 \(2\),取 \(X\) 为全 \(0\) 串,\(Y\) 为奇数位 \(1\),偶数位 \(0\) 的串,则 \(W(X) = 0, W(Y) = 2\lceil n / 2 \rceil\)。因此必定有 \(f(n) \geq \lceil n / 2 \rceil\)。
然后你考虑归纳构造,简单来说就是找到 \(n = 10\) 时的 \(5\) 步构造,则可以一次操作让当前最左侧连续 \(10\) 个 \(X\) 与 \(Y\) 不同的位置变得相同。将 \(n\) 写成 \(10m + r\) 的形式,其中 \(r \in [4,18]\),这个是因为可能不能直接取到 \(4\) 导致总构造次数大于 \(f(n)\)。然后将字符串从左到右分为 \(m\) 个长度为 \(10\) 的块和一个长度为 \(r\) 的块,每一块独立建出:
- 对每个 \(10\) 长度的块,预处理所有状态之间的最短路,每块至多 \(5\) 次操作。
- 对长度为 \(r\) 的尾块,双向 BFS 求状态最短路。
- 对 \(4 \leq n \leq 8\) 的块,直接对整个串求最短路。
因为块内操作在整个串内均合法,所以总操作数 \(5m + \lceil r / 2 \rceil = \lceil n / 2 \rceil = f(n)\)。一些卡常大概是,对所有 \(n \in [4,8]\) 的情况可以类似于 IDA* 优化,以及就是用 unsigned long long 代替 std::string,最大的优化是你考虑双向 BFS 对应状态空间本质相同,所以可以直接对 DFA 优化,每次转移极小的未转移过的边,并记录类似的转移可达性,这样可以复用在另一侧。
浙公网安备 33010602011771号