刷题杂记 Pt.7

2025.8.19

今天只写了一道题,主要原因是状态不佳。我保证明天绝对写够三道题。


2025.8.20

结果今天还是没有写够两道题(

  • P8330 [ZJOI2022] 众数:根号分治好题。还没写完。。。

    1. 看到众数,联想根号分治。本题采用的方法就是在出现次数上做根号分治。

    2. 计算两个不独立的部分的贡献和的最值时,可以考虑先将一部分全部选上,再扣去其贡献。


2025.8.21

差点写够。

  • P8290 [省选联考 2022] 填树:拉格朗日插值优化 DP 经典题。

    1. 限制为“必须取得某个值”的处理方法:一种是容斥;一种是将 DP 增加一维,表示是否已经取得这个值。前者的常数会小一些。

    2. 树形 DP 统计路径的方法:感觉一般都是维护向下的两条路径,然后再 LCA 处拼起来。

    3. 使用拉插时,如果感觉实际的区间端点应在所处理出的区间端点周围 +/-1 的位置,其实往往是无所谓的。

  • P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I:经典分块题。我还在卡常。

    1. 做分块题可以有这么一种思考模式:将问题分为“整块对整块”、“零散块对整块”、“零散块对零散块”以及“每个块内部”这几种情况。

    2. 当信息可差分时,对每个块维护一个表示这个块及这个块前信息的标记桶是常见套路。

    3. 做分块问题时,一定要结合这个问题在平凡情况下(比如本题就是静态整体逆序对)的解法。


2025.8.22

Week 1:总题量 8,其中黑题 2 道,紫题 6 道。


2025.8.27

  • P5069 [Ynoi Easy Round 2015] 纵使日薄西山:线段树结构体设计类题目。这告诉我们:如果感觉信息可能满足结合律,即可尝试用线段树维护。

  • P5070 [Ynoi Easy Round 2015] 即便看不到未来

    1. 二维数点问题,可以考虑调换修改与询问的“点”“面”,往往可以优化复杂度。(表达不清晰致歉。)

    2. 他在分析性质的时候切换了一种思考方式——从段合并形成新段来思考。感觉很牛,不知道怎么想到的。


2025.8.28

  • 联考 T3

    在二维平面上,有两个点集,大小分别为 \(t, n (t \le 20, n \le 2 \times 10^4)\)。给定一个常数 \(m (m \le 4)\),你需要在第二个点集中选出 \(m\) 个点,与剩下的一个点集中的 \(t\) 个点组成一个新的大小为 \(m + t\) 的点集,使得该点集满足两两之间的曼哈顿距离之和尽量大。

    贡献可以分为三部分:第一个点集内部、第一个点集与第二个点集之间、第二个点集内部。第一部分显然可以预处理,第二部分可以对每一个点预处理,重点在如何得到第三部分的贡献。

    先考虑点只有一维的情况。将点集从小到大排序。考虑费用提前计算,对选出的第 1 到 2、2 到 3、3 到 4 的点之间的段,分别计算贡献。如此就有一个线性 DP 做法。

    对于二维的情况,我们依旧对第一维排序,并用上面的方法维护。对于第二维,考虑到绝对值本身即带有“取最大值”的特性,我们考虑选出 \(m\) 个点以后,对它们的 \(m!\) 种排列顺序全部求一遍即可。这一过程即可通过状压 DP 实现。

    这个做法爆标了。不过其实本质上和题解做法也大差不差,只是出题人他可能脑抽忘记了这可以爆标。

  • P5071 [Ynoi Easy Round 2015] 此时此刻的光辉:莫队 + 根号分治。这种数论相关问题,有时可以调整分治阈值至 \(n^{1/3}\)


2025.8.29

  • 联考 T3

    给定一张 \(n\) 个点 \(m\) 条边的 DAG,第 \(i\) 个点有点权 \(a_i\)。对于每一个点求出,在其能直接或间接到达的点中(包括自身),选出两个点 \(x, y\),所能得到的 \(a_x \operatorname{and} a_y\) 的最大值。\(n \le 5 \times 10^5, m \le 10^6, 0 \le a_i < 2^{60}\)

    好像又爆标了喵喵。。。

    题解提供的做法是考虑缩减每个点储存的有效后继数量。设 \(w\) 为二进制数位数,当前答案为 \(ans\),那么 \(< ans\) 的点不用保存,\(= ans\) 的点最多保留两个,\(> ans\) 的点经过某种分析好像最多保留 \(O(w)\) 个。如此总复杂度为 \(O(mw^2)\),但是由于常数很小跑得飞快。

    爆标做法:考虑整体二分。大致流程就是从高位到低位考虑答案这一位是否能填 1,把能填 1 的点分到一组,填 0 的分到另一组,然后继续往下递归。首先,如果某个点能填 1,则其前驱一定都能填 1;其次,某个点能填 1 当且仅当其有至少两个该位为 1 的后继。所以每次二分判定时就这么做:以正常 DAG 的 DP 流程从后往前推,一旦某个点出现了 \(> 1\) 个为 1 的后继,那么就停止这个点的前推,并将其所有为 1 的后继记录下来,用于下一层递归的前推。由于非停止点都至多只有一个为 1 后继,故停止点最多记录 \(O(\text{outdegree})\) 个后继,记录的总数就是 \(O(m)\) 个。总复杂度为 \(O(mw)\),但是常数比较大,跑不过前面的做法。


2025.9.1

NFLS 线上 Day1。

  • T1:最大矩形/正方形类问题,一般考虑二分或者单调队列。

  • T2:排列类计数题,这类问题的最基本的思考方式是考虑哪些数值已经被填了/哪些位置已经被填了。所以为了更方便地确定这些信息,我们在此题中按照最小值从大到小处理限制。

  • T3:浮点数误差分析。一个很有意思的 Trick 是,当遇到分子分母都很大但结果很小的一个分式时,可以通过取对数的方式将值域缩小到一个可计算的范围内。当然前提是此题必须是浮点数相关问题。

  • T4:略。

  • P5610 [Ynoi2013] 大学

    1. 二分 + 并查集可以以更小的常数替代 finger-search 平衡树(限制包括不限于只有删除操作,感觉应用很局限)。

    2. 手写静态 vector 数组:先计算每个 vector 的 size,再插入数。


2025.9.2

NFLS 线上 Day2。

总分 240,rk 31/59。

  • T1:由于数据随机,可以乱搞。我采用的乱搞方法是特判掉一些绝对不可能合法的位置。题解则是枚举所有的因数。

  • T2:又是乱搞题。我在考场上的做法是根号分治,阈值是随便估了一下设出来的,没有严格证明。另一个很简单的做法是直接暴力松弛,也没法卡。做这种乱搞题的关键就在识别它是乱搞题。。。

  • T3:最关键的一点在用组合意义转化这道题统计的对象。显然这个 \(k\) 次方有一个组合意义是每个矩形中选 \(k\) 个点,所以可以转化为先选出 \(k\) 个点再计算矩形个数。

    题解中有一个减少分类讨论的好写法。从小到大对 \(p_j\) 做扫描线,将 \(< p_j\) 的点设为 \(0\),其余设为 \(1\),然后就容易用线段树维护这几类点。


2025.9.4

  • P4458 [BJOI2018] 链上二次求和:不管是什么做法都要分析出此题需要维护四阶差分上单点修改单点询问。

    接下来有两种想法:一是用线段树维护二阶前缀和,并带区间修改区间查询;另一种是直接将贡献拆为三次多项式,用树状数组维护单点修改单点查询。对于后者,在拓展到 \(k-1\) 次多项式的情况下,可以用二项式定理处理一下多项式平移,不然徒手拆式子很麻烦。

    实现时注意分析清楚差分的 +/-1 问题。

  • P11392 [JOI Open 2019] 三级跳 / Triple Jump:拼尽全力无法战胜。这类题叫做“支配对”问题,即通过削减无用的二(三)元组减少时间复杂度。这道题没做出来的主要问题是他给定了 \(a < b < c\) 三个数,我一直在分析怎么削减 \((a, c)\),结果正解是削减 \((a, b)\)。。。

  • P9331 [JOIST 2023] 护照 / Passport:拼尽全力无法战胜。线段树优化建图问题。关键在将这个与很多点相关的最短路问题转化为只与 1, n 相关的单源最短路问题。最后求一个点到两个点最短并路的 Trick 也很巧妙。


2025.9.5

NFLS 线上 Day3,得分 0,rk inf。

  • T1:这个题纯粹考场上唐氏了。一直在想

2025.9.6


2025.9.8

NFLS 线上 Day5,得分 80,rk 57/58

  • T1:简单 DP 题,但是挂了 40pts。。。原因是没有意识到循环移位的下标要从 0 开始不然取模容易出错。神秘的是竟然没有样例拍出来错误??

  • T2:这道题没做出来感觉有一定程度上是因为知道得太多。。。

    首先考虑枚举下标 \(i\) 并计算将 \(S_i\) 移到 \([L, R]\) 之间的最小代价。有这么一种 DP 的方法:将 \(j \le i\) 的物品体积设为 \(-A_j\),否则设为 \(A_j\),跑一下 01 背包即可。这种方法的复杂度是 \(O(n^3w)\) 的。

    考虑怎么去优化这个 DP。然后,由于我考场上联想到了 P8392,就成功地走歪了:可以通过先尽量选最大,再将物品按体积绝对值大小排序,将背包值域缩到 \([-w, w]\) 的范围内。但是这个方法依旧是 \(O(n^2w)\) 的,既难写又没有优化前途。

    考虑到枚举哪个下标 \(i\) 被移到 \([L, R]\) 这一步是绝对省不掉的,我们尝试将 \(\le i\)\(> i\) 的部分分开计算。这道题的背包与 P8392 的不同处就在于,容易证明 \(> i\) 的部分背包值域仅为 \([0, R]\),而对于 \(\le i\) 的部分如果我们 计算其反情况(即维护哪些物品不选) 那么背包值域也仅为 \([0, R]\)!此时可以做到一个很好写的 \(O(nw^2)\),瓶颈在对每个 \(i\) 枚举左右选出物品的体积和。容易发现这里可以用单调队列优化到 \(O(nw)\),问题解决。

  • T3:暂且咕了,还没调出来。

  • CF765F Souvenirs:支配对问题。关于怎么猜结论:看到这种与“差值”有关的最优化问题,考虑是否只有 \(O(\log w)\) 个最优值。


2025.9.9

NFLS 线上 Day6,得分 260,rk 15/56

  • T1:神秘结论题,考场似乎有一车人直接 OEIS 过了。

    需要积累的关于冒泡排序的结论:可以考虑每一个 \(k = p[i]\),将数分为 \(\le k\)\(> k\) 考虑;冒泡排序的总轮数为 \(\max_{i=1}^n \sum_{j < i} [p[j] > p[i]]\)

    一个打表 & 优化 DP 的方法:考虑数组的前缀和 / 差分数组

  • T2过河卒 简化版。

  • T3

    当我们在 DAG 上判断一条边是否为必经边时,我们可以通过比较经过它的路径数以及总路径数来判断。

    这道题使用的就是类似的思想。由于 LIS 和 LDS 只有一个交点,我们枚举所有点,并算出同时经过这个点的 LIS 和 LDS 的对数。将所有这些对数加起来,再与总对数进行比较,我们就能判断是否有解。

    然后考虑构造出一个合法的 LIS,把它删掉以后再跑一次就能求出 LDS。容易发现,只要与这条 LIS 相交的 LDS 总数小于总对数,这条 LIS 就一定合法。于是,我们只要构造出两个相交 LDS 总数不同的 LIS,就一定能得到一个合法的 LIS。

    巧妙的点:

    1. 使用了 DAG 中的“必经边”判断思想。

    2. 利用鸽笼原理,如果让你求 \(\ne x\) 中的元素的最值(或者构造任意一个解),那就维护两个值。这个 Trick 前几天在那道最短路题中也用到了。


2025.9.10

  • P4632 [APIO2018] 新家:使用了区间数颜色“维护该颜色上一次出现的下标”的思想,但是并不是直接这么做。注意到我们只需要判定 \(k\) 种颜色是否全部出现,只要通过判定 \(> r\) 的位置是否有前驱 \(< l\) 即可。告诉我们,如果发现思考的时候没有思路了,可能是因为这道题的某些特性被我们忘了

  • P6109 [Ynoi2009] rprmq1:线段树维护区间历史最大值 + 猫树分治。猫树分治其实就是考虑过中点的区间,将左区间右区间贡献拼起来。它的效果是能够将修改转为静态(?)。使用条件就是信息必须满足可并性

    另外关于这道题的线段树部分:撤销操作可以通过设置一个将历史最大值重置为当前最大值的标记实现。求历史最大值需要维护一个历史最大 tag。我的写法要再维护一个是否要更新历史最大值的 tag;当然也可以不要它,不过需要注意同一行内负数要在正数前插入线段树。

    写多 tag 线段树时,一定要注意 tag 的更新顺序。实在想不出来的,使用矩阵维护。


2025.9.11

  • CF997E Good Subsegments

    1. 形式化你需要维护的东西。但需要注意的是,形式化的过程可能会丢失少许信息,你不能完全依赖于此。

    2. 线段树有区间数最值个数的功能。这里我们在保证区间所有数 \(\ge 0\) 的情况下,可以用来数 0 的个数。

    3. 依旧是多 tag 线段树的问题。分析可以发现历史和 tag 与区间加 tag 之间的关系并不大,所以不太用考虑这个问题。

  • P11630 [WC2025] 士兵(暂无数据):还是比较套路的数据结构优化 DP。我不太理解当时我考场上为什么没有做出来,今天还推了这么久才做出来。当时 VP NOI2025 时 D1T2 的 DP 也瞪了半天没有瞪出来是 DP。。。要加训 DP!

    Hint:\(O(n^2)\) 的 DP 类型有两种:

    1. f[i][j] <- f[i-1][k]

    2. f[i] <- f[j]

    你往里面选就行了。这道题可以猜到是第一种类型。


2025.10.27

  • CF1842G Tenzing and Random Operations

    very educational。我在这里记录几个不同的做法。

    所有做法开始都先将期望转计数。即,最后再在整体上除以 \(n^m\)

    • 看到这种连乘式,可以从其组合意义角度考虑。那么问题转化为:有 \(n\) 堆物品排成一排,第 \(i\) 堆有 \(a_i\) 件不同的物品,现在你要往每一堆里面选一件物品;但是你可以在行动开始前执行 \(m\) 次操作,每一次操作可以任选一个位置,并在其后的每一堆物品中放入 \(v\) 个新的不同物品;问总方案数。

      此时有一个 DP:设 \(f[i][j]\) 表示,在第 \(i\) 堆处,还剩 \(j\) 次操作没有使用的方案数。然后有显然 \(O(nm^2)\) 转移。

      DP 的优化十分难想。考虑费用推后计算:如果我们选了附加物品,我们实际只关心被选中的来自哪一次操作,别的操作增加的物品我们都不关心。所以设 \(f[i][j]\) 表示前 \(i\) 堆其中有 \(j\) 次都选择了附加物品的方案数,每次转移可以选已经选过的附加物品,或者没有选过的附加物品,并且我们在引入新的附加物品时再为其分配操作位置和编号。

      这么说来其实那个基础 DP 已经用了一点费用推后计算的思想了,因为不是按照操作顺序进行的,而是用到这个操作时再给他分配编号。

      其实将将连乘式拆开和考虑组合意义是等价的。但是一个直观的组合意义更能帮助我们思考问题。

    • 生成函数暴力推。因为转移式中含组合数,我们这里使用 EGF。设 \(G_n = \sum_{i=0}^{\infty} \dfrac{f_{n, i}}{i!} x^i\),此处的 \(f_{i, j}\) 与上一种方法中的 DP 式含义相同。那么根据上面的转移,有:

      \[G_n = a_n (G_{n-1} \times e^x) + vx (G_{n-1} \times e^x)' \]

      这里我们用求导来解决 \(f_i \leftarrow f_i * i\)。然后化简一下:

      \[G_n = e^x ((a_n + vx) G_{n-1} + vx G_{n-1}') \]

      接着的优化还是需要动一些脑筋的。猜测 \(G_n\) 一定可以被表示为 \(e^{nx} \times \sum_{i=0}^n p_{n, i} x^i\) 的形式(毕竟有这个数据范围摆在这里,你肯定要做一个 \(O(n^2)\) DP 对吧)。我们尝试归纳证明:

      \[\begin{aligned} G_n &= e^x \left(e^{(n-1)x} (a_n + vx) \left(\sum_{i=0}^{n-1} p_{n-1, i} x^i\right) + vx \left((n-1)e^{(n-1)x} \sum_{i=0}^{n-1} p_{n-1, i} x^i + e^{(n-1)x} \sum_{i=1}^{n-1} i p_{n-1, i} x^{i-1}\right)\right) \\ &= e^{nx} \left( \sum_{i=0}^n ((a_n + vi) p_{n-1, i} + nv p_{n-1, i-1}) x^i \right) \end{aligned} \]

      这顺带给出了 \(p_{n, i}\) 的递推式。(当然,我上面的推导没有处理 \(i=0\) 的边界情况,请忽略这一点。)

      现在的问题是我们应该如何求出 \(m! \times G_n [x^m]\)。推导容易有:

      \[\begin{aligned} m! \times G_n [x^m] &= m! \sum_{i=0}^n p_{n, i} \times e^{nx}[x^{m-i}] \\ &= \sum_{i=0}^n p_{n, i} m^{\underline{i}} n^{m-i} \end{aligned} \]


反悔贪心

已严肃被反悔贪心击败,故来进行一波学习。(话说现在的蓝题难度怎么都这么高。。。不会 NOIP 我又没法切蓝题吧。。。)

解决反悔贪心的最好方法是?——模拟费用流?但是一个很恼火的问题是我的网络流基础也不好。我没法很快地给出一个合适的网络流建模。所以感觉我还得去复习一下网络流,真的很烦。

  • P3045 [USACO12FEB] Cow Coupons G

    二分一下奶牛的头数,然后尝试计算最小钱数。可以这么构建费用流模型:\(s\) 有初始容量 \(mid\),其连接两个点 \(s_1, s_2\),容量分别为 \(\inf, k\)\(s_1, s_2\) 分别连接 \(1 \sim n\),容量为 \(1\),费用为 \(p_i\)\(c_i\);对于 \(1 \sim n\) 中的 \(i\),连接 \(t\),容量为 \(1\)。当然,由于费用流凸性,我们可以动态加边,直到总费用超过 \(m\) 为止,这样就不用二分了。

    考虑怎么模拟费用流。关键在分析增广路的形态。显然有这么几种基本情况:

    1. \(s_1\) 出发,找到一个没被选过的 \(i\),有代价 \(p_i\)

    2. \(s_2\) 出发,找到一个没被选过的 \(i\),有代价 \(c_i\)

    3. \(s_1\) 出发,找到一个被 \(s_2\) 选过的 \(i\),退流,给 \(s_2\) 重新选一个 \(j\),有代价 \(p_i - c_i + c_j\)

      这应该是可行的。不过,有没有可能,我们会对 \(s_1\) 再进行一次退流重选呢?

      答案是不会。考虑如果这样,那么增广路会在图上经过一个环。而根据费用流结论,图上的任意时刻都不会存在负环,故去掉该环后一定更优。这是模拟费用流分析路径形态的一个关键结论。

    4. \(s_2\) 出发,找到一个被 \(s_1\) 选过的 \(i\),退流,给 \(s_1\) 重新选一个 \(j\),有代价 \(c_i - p_i + p_j\)

      这种情况和上一种情况是同理的。不过,由于明显前 \(k\) 次的增广路我们一定会选择从 \(s_2\) 走,这种情况并不会真的发生。

    于是我们有算法:先选 \(k\) 个最小的 \(c_i\)。然后维护三个堆,分别维护还没选的 \(p_i, c_i\) 以及选了的 \(p_i - c_i\) 的最小值。

  • P14361 [CSP-S 2025] 社团招新

    感觉现在题目难度真的在通货膨胀。这题放以前包是个绿的。

    依旧尝试费用流。这题的建模很显然,由 \(s\) 向每个点 \(i\) 连一条容量为 \(1\) 的边,再由每个点 \(i\)\(1,2,3\) 分别连接一条容量为 \(1\) 费用为 \(a_{i,1}, a_{i,2}, a_{i,3}\) 的边,最终由 \(1,2,3\)\(t\) 连接一条容量为 \(n/2\) 的边。

    然后是模拟费用流部分。一开始一定是选最大的 \(a_{i,j}\),直到 \(1,2,3\) 中某一个点达到 \(n/2\) 的临界。接着开始反悔。显然退流方式只有一种,即从那个满流点退回去然后重新选一个。又由于 \(n/2\) 这个阈值的特殊性,每时每刻 \(1,2,3\) 中一定只有一个点达到 \(n/2\) 临界,所以只维护一个堆就可以了。

    如果直接从反悔贪心的角度思考,我们可以得到一个更为简洁的做法。先对每个人粗暴选择其最优社团。注意到此时只有至多一个社团有 \(> n/2\) 个人,那么就调整一下使得其人数 \(\le n/2\) 即可。放到费用流上考虑的话,这可以看作先去掉 \(1,2,3\)\(t\) 的边的容量限制,最后从 \(t\) 开始跑费用流,等价于退流操作。这里告诉我们一个道理,对于模拟费用流的题目,除非像前一道题那种钦定了顺序的情况,我们先随便将一些边流满甚至是流得超出容量,然后再进行退流操作,这样写起来会方便一些(比如可以少维护一些堆)。

  • P2949 [USACO09OPEN] Work Scheduling G

    首先,如果想要做这道题,一定得有一个核心观察:题目条件等价于按照 \(d_i\) 排序后,前缀 \(i\) 中被选择的工作数量 \(\le d_i\)。然后有显然的费用流建模:\(s\) 向每个 \(i\) 连接一条容量为 \(1\) 费用为 \(p_i\) 的边,\(i\)\(i+1\) 连接一条容量为 \(d_i\) 的边。

    接着有两种思路:

    1. 直接在这个图上模拟费用流。使用树状数组 + 二分可以维护。

    2. 按照 \(i\) 从小到大,每次新增一条 \(s\)\(i\) 的边,每次尝试会不会新增一条增广路。使用堆容易维护,写起来比前一种方便。

    此题告诉我们,我们还可以边建图边做费用流,同时每次不一定要找到一条增广路。

    另外,此题还有一个非常牛的做法。考虑时间倒流,这样就变成在 \(d_i\) 时间会出现一个新工作,且它直到 \(0\) 时刻都不会消失。于是每次选择利润最高的工作即可。

  • CF730I Olympiad in Programming and Sports

    容易发现这道题的费用流建模同 P3045 是几乎一致的。

    虽然这道题并未保证 \(b_i, a_i\) 有什么大小关系,但为了写起来方便,我们可以先暴力选上其中一者的最小值。

  • P4053 [JSOI2007] 建筑抢修 & P11457 [USACO24DEC] Job Completion G & P11328 [NOISG 2022 Finals] Gym Badges

  • UOJ984 欢迎来到最前线

posted @ 2025-08-20 22:18  David_Mercury  阅读(58)  评论(0)    收藏  举报