刷题杂记 Pt.3

  • P8421 [THUPC2022 决赛] rsraogps

    • 给定 \([l, r]\),询问满足 \([l', r'] \subset [l, r]\)\([l', r']\) 的价值和。经典题型,几种思路:

      1. 离线扫描线。移动 \(r\),数据结构内对每个 \(l'\) 维护当前所有 \(r'\) 的价值和(等价于维护历史和),每次做区间和。

      2. 对每个区间维护前缀和、后缀和,做拼凑。

      3. 考虑每个数对整体的贡献。

    • 典型的均摊时间复杂度运算:\(\gcd, \text{bitand}, \text{bitor}\),以及整除、区间覆盖。

    • 维护历史和的 Trick:总历史和 \(=\) 当前和 \(\times\) \((\) 当前时间 \(-\) 上次时间 \()\) \(+\) 前历史和。这样我们可以在不支持线段树打标记的情况下维护历史和。

  • P5292 [HNOI2019] 校园旅行

    • “转化为暴力”型题目。

    • 在保持想要的性质不变的前提下,对图进行简化。常见的简化方式是保留图的生成树。这种题的关键是考虑环对路径的影响。类似 Trick 题目:P4151 [WC2011] 最大XOR和路径

    • 先分而合:本题对不同种类的连通块分别进行讨论,然后再将他们合在一起。

  • P5290 [十二省联考 2019] 春节十二响

    • “子树合并”是树上问题的基本想法。

    • 长链剖分一般在合并有关长度时被用来进行优化;这时其实用启发式合并复杂度是一样的(也是 \(O(n \log n)\))。

  • P5840 [COCI2015] Divljak

    • AC 自动机解决问题的基本思路为:先插入模式串,每次操作文本串,然后对 fail 树做操作。

    • 处理树上问题的两个角度:

      1. 插入时,修改其所有祖先;然后单点询问。

      2. 插入时单点修改;询问时,查询其子树。

      一般来说,方法 2 在实现上是更为简洁的;但方法 1 可能会更好思考。而方法 1 往往能够通过做树上差分变为方法 2。

    • 虚树思想:将关键点按照 \(dfs\) 序排序后,取相邻两个点的 \(lca\) 就可以得到虚树。

      这种题目往往不需要真正建出虚树。如本题,求关键点到根的路径并,可以直接树上差分;以及 P3320 [SDOI2015] 寻宝游戏,求关键点之间的路径总长。

  • P3215 [HNOI2011] 括号修复 / [JSOI2011]括号序列

    • 线段树没法做区间翻转!只能用文艺平衡树!

    • 做数据结构题时,将每一个步骤怎么做想清楚再开写。

  • P5363 [SDOI2019] 移动金币

    阶梯 Nim + 插板法 + 整体减空白简单容斥 + 简单 DP。。。

  • P3153 [CQOI2009] 跳舞

    二分答案 + 拆点建图 + 最大流。

  • P5445 [APIO2019] 路灯

    • 两个思考角度:考虑修改对每个询问的影响;直接考虑询问。如果你发现无修改情况特别好做,但一旦引入修改就很复杂,不妨从前者想想。

    • “区间 \(\rightarrow\) 二维数点”

    • 动态二维数点问题

      • 操作类型:平凡情况支持单修区查,做差分后可以支持区修单查。区修区查……可能可以在 KD-Tree 上做。

      • 适用数据结构:二维线段树、树状数组套主席树、线段树套平衡树、CDQ 分治、KD-Tree。

    • 维护历史和的 Trick:总历史和 \(=\) 当前和 \(\times\) \((\) 当前时间 \(-\) 上次时间 \()\) \(+\) 前历史和。(用于不方便线段树打标记的情况。)

      这道题中,我们使用了支持历史和的树状数组。实现过程中,我们不用将式子拆开(即分别维护“当前和 \(\times\) 上次时间”、“当前和”、“前历史和”),只需要对每个下标分别维护“当前和”、“上次时间”、“前历史和”三个值,每次在树状数组中更新该下标的时候就顺便改即可。

  • P3979 遥远的国度

    • 在树论问题中遇到“换根”操作时,我们可以保持根不变,而是考虑换成的根会让子树范围产生什么变化。类似 Trick 题目:P4689 [Ynoi2016] 这是我自己的发明
  • P3225 [HNOI2012] 矿场搭建

    圆方树好题。

    遇到圆方树题目,先考虑树上做法,这样会有助于思考。但也要注意圆方树本身结构的特殊性(比如连通性、圆点根、孤立点……)。

  • P4563 [JXOI2018] 守卫

    实际这道题分析得并不够透彻,但碰巧也做出来了。。。

    因为我做的时候忽略了区间 DP 自带的“决策包含性”,即我们不用在每一步把状态划分得那么“完美”,往往来说把一个区间划分为两个就够了。比如此题,如果我们考虑 \(r\) 必须放置的性质,我们只需要找到下一个完全无关、且满足区间性质的区间即可。

  • P3688 [ZJOI2017] 树状数组

    • 概率 / 期望可以相乘,当且仅当二者互相独立。

    • 二维数点问题:本质上实际是三维偏序问题。

      算法 / 数据结构 在 / 离线 动 / 静态 修改 & 询问 时间复杂度 空间复杂度
      CDQ 分治 离线 动态 一维单修前缀查(若满足可减性,可以单修区查 / 区修单查),另一维区修区查 \(O(n \log^2 n)\) \(O(n)\)
      扫描线 离线 静态 同上 \(O(n \log n)\) \(O(n)\)
      主席树 在线 静态 同上 \(O(n \log n)\) \(O(n \log n)\)
      树状数组套主席树 在线 动态 同上 \(O(n \log^2 n)\) \(O(n \log^2 n)\)
      二维线段树 在线 动态 两维区修区查(相比以前的优点是不满足可见性但可合并的信息都支持;但必须标记永久化,前提信息满足交换律) \(O(n \log n)\) \(O(n \log^2 n)\)
      线段树套平衡树 在线 动态 单修区查 \(O(n \log^3 n)\)(含区间数排名查询) \(O(n \log n)\)
      kD-Tree 在线 动态 关键点可以单个插入删除,关键点信息支持区修区查 \(O(n \sqrt{n})\) \(O(n)\)

      本题为典型的二维线段树。

  • P4130 [NOI2007] 项链工厂

    不要一看到什么“翻转”就想到平衡树——这个题有趣的地方在于它将对序列的“旋转”“翻转”转化为对每个下标的“变化量”的操作。具体怎么变的?你可以推导两个操作分别会对变化量带来什么影响,是系数项的变化还是常数项的变化,然后分开维护,就像维护线段树标记那样。

  • P5336 [THUSC2016] 成绩单

    明显的区间 DP。Trick:将两个 DP 数组嵌合在一起使用,当你推当前设出来的 DP 的转移方程时如果遇到困难,不妨再设一个别的。

  • P6088 [JSOI2015] 字符串树

    可持久化数据结构 + 树上差分。

  • P6835 [Cnoi2020] 线形生物

    打破了随机游走期望 DP + 高斯消元的套路,而是用线性性拆解得到简单的递推式。

    当然,还有一种从简化高斯消元的角度出发的方法。。。

  • P2447 [SDOI2010] 外星千足虫

    我是脑残,“若干个数异或”这种关键词肯定得想到 线性基 啊。。。

  • P2481 [SDOI2010] 代码拍卖会

    特别好的一道题。

    • 拆数

      第一步转化有两种方法。一种是将数拆解为 \(9\)\(111\cdots\) 的后缀和(将满足单调性的序列转化为其差分序列统计);一种是看见 \(aaa \cdots\)\(a\) 为数码)的经典 Trick,即将其拆为 \(a \times \frac{10^{len}-1}{9}\),再通过裂项可以得到和第一种方法类似的结果(在这道题中,要特判 \(9 \equiv 0 \pmod{p}\),即 \(p = 1, 3, 9\) 时只能用矩阵快速幂计算)。

    • 循环节的计算

      可以感觉一下,不论是上面的 \(111 \cdots\) 还是 \(10^k\),在 \(O(p)\) 次迭代后关于 \(p\) 的模数都会进入循环节。暴力预处理即可。

      (作为一个学过数论的人我怎么能不知道这些呢 :(

    • 分组背包

      我们现在得到了每个余数对应的 \(111 \cdots\) 的数量。现在的问题等价于求出满足点权和余数为 \(0\)可重集 数量。一个简单的想法是这么执行背包的循环的:

      1. 当前已经放入 \(i\)\(111 \cdots\)

      2. 当前余数为 \(j\)

      3. 新放入的余数为 \(k\)

      但这样求出的是一个 序列 而非 可重集。解决方法实际也很简单:最先循环放入的余数是什么。这样我们就限制每个数只能被加入一次,等价于 分组背包 中在第一维循环组限制每组仅选一个的道理。

      最后还有一点。若同一个余数有 \(n\) 种方案,在其中选出 \(m\) 个,这实际等价于 无限多重集的组合数 问题。而这与 插板法 本质是相同的,因为可以看作将 \(m\) 个小球分成可空的 \(n\) 个组。

      这里补充一点我没有看出来这是插板法时用生成函数推导的做法。可以发现,无限多重集的组合数有如下生成函数表达式:\((\sum_{i=0}^{\infty} x^i)^n[x^m] = (1-x)^{-n}[x^m] = \sum_{i=0}^{\infty}\binom{-n}{i}(-x)^i[x^m] = \sum_{i=0}^n\binom{n+i-1}{i}x^i[x^m]\)。故答案为 \(\binom{n+m-1}{m}\)

  • P5385 [Cnoi2019] 须臾幻境

    • 用生成树来维护图的连通性。然后再贪心一下,就转为维护其最大生成树了。

    • LCT 维护边信息需要边化点。

  • P3965 [TJOI2013] 循环格

    我一开始做这道题时没有看出来这是二分图最大权完美匹配,而是从上下界无源汇最大权可行流推过来的,某种意义上发现了前者为后者的特殊形式。

  • P4117 [Ynoi2018] 五彩斑斓的世界

    第二分块。

    • 分块题,可以先思考只存在整体操作时怎么做。

    • 减小值域的角度入手,即将值域作为复杂度势能函数。

    • 合并以后就不会再分开,想到并查集。不要忘记并查集既有路径压缩又有按秩合并时是 \(O(n)\) 的。

    • 卡空间方法:将询问离线,对每一个块单独做。前提是块之间独立,且答案满足可加性

  • P5904 [POI2014] HOT-Hotels 加强版

    没有想到简单的树形 DP 方法。。。于是还套了一个点分治。。。

    那个树形 DP 的关键在你要大胆设。也是两个 DP 数组配合解决的问题。

    然后就是长链剖分,因为这是与长度相关的树形 DP。时间复杂度注意是 \(O(n)\) 没有 \(\log\)

  • P3248 [HNOI2016] 树

    真 · 树套树。

    • 这里面在线查询区间第 \(k\) 大,要敏感地想到主席树。

    • 然后注意一下路径的分讨即可。

  • P4322 [JSOI2016] 最佳团体

    01 分数规划 + \(O(n)\) 祖先依赖树形 DP。

  • P3736 [HAOI2016] 字符合并

    Huffman 式区间 DP(每次合并必须合并相邻 \(k\) 个字符,并生成一个新字符)。有结论:

    如果当前区间长度为 \(len\),则最终得到区间长度一定为 \((len-1) \bmod (k-1) + 1\)

  • P3592 [POI2015] MYJ


鸽了好久没写(


这里是套题总结。

2024.10.1 牛客

  • T4

    • 二维 DP \(\rightarrow\) 网格图最短路。

    • CDQ 分治动态询问网格图最短路,时间复杂度 \(O(nm \sqrt{nm} \log nm)\)

2024.10.2 清北学堂day1

  • T2

    • 一种新的字典序最小 01 字符串:构造一组解,然后再调整使其为字典序最小。(注意:后缀字典序最大”不等价于“前缀字典序最小。)

    • bitand,bitor 之间虽然不满足结合律,但它们内部满足。

    • bitand,bitor 都是具有覆盖性质的运算。这往往可以帮助我们进行某些从后往前的贪心。

2024.10.3 清北学堂day2

  • T2

    现在解决二维的枚举问题有一种新思路——根号分治。如果你有一个 \(O(x^2 y)\) 的枚举算法,不妨钦定较短的一维为 \(x\),较长的一维为 \(y\)

  • T3

    ...

2024.10.4 清北学堂day3

  • T3

    gcd 卷积。形式化的定义为:给定函数 \(F(x), G(x)\),求 \(H(x) = \sum_{\gcd(i, j) = x} F(i) * G(j)\)

    可以先计算 \(H\) 的倍数后缀和,这等于 \(F, G\) 的倍数后缀和分别相乘;然后再做一次倍数差分即可得到 \(H\)

2024.10.5 清北学堂day4

  • T4

    关于形成三角形的巧妙 Trick:

    1. 给定若干数,如果其存在能够形成三角形的数,则它们一定在前 \(\log w\) 大的数中出现。

    2. 如果在给定数列中,最大值能够与剩下的数中的某两个形成三角形,那么最大值一定能与次大值、次次大值形成三角形。

2024.10.9 洛谷网校秋令营提高组day1

  • T3

    遇到末状态相同、初始状态不同的 DP,可以考虑做倒推。

2024.10.10 洛谷网校秋令营提高组day2

  • T3

    归纳构造(贪心)+ 图论建模。我们在考虑比较若干菊花图大小关系的时候,可以将过程抽象为“合并”两个菊花图,这样就可以转化为一个子问题,更好思考。

  • T4

    ...

2024.10.11 51nod

  • T3

    ...

2024.10.16 清北学堂day6

  • T1

    ...

2024.10.17 洛谷NOIP模拟14

  • T3

    • 拆贡献。将统计每个排列的点对个数转化为计算每个点对的排列个数。

    • 妙到极点的想法:转化为枚举两段,然后可以用二阶前缀和维护对答案的贡献。接着由于段数满足本质不同的不超过 \(\sqrt{n}\),能够 \(O(n)\) 过掉该题。

2024.10.18 洛谷NOIP模拟19

  • T2

    DP 优化策略:仔细观察,将没有用的状态放到数组中当作计算的值。

  • T4

    优化背包值域大小 Trick:先尽量贪心放入,再用背包做。

    原题:P8392 [BalticOI 2022 Day1] Uplifting Excursion

2024.10.21 洛谷NOIP模拟16

  • T2

    1. 遇到在相同限制条件下末状态相同、初始状态不同的 DP,可以考虑做倒推。

    2. 遇到初始状态相同,而限制条件不同的 DP,可以试着转化为 1 中的情况。

  • T3

    关于合法括号序列的 Trick:

    1. 任意时刻,都有 \(cnt_L \ge cnt_R\),且最终有 \(cnt_L = cnt_R\)

    2. ( 值为 +1) 值为 -1,则值每时每刻为正,且最终为 0。

    (关于上面两个性质,我一时忘记了在哪些地方有所应用,有机会补过来。)

    1. 一个长度为 \(2n\) 的括号串合法,当且仅当所有左括号的位置能被 \(1, 3, 5, 7, \dots, 2n − 1\) 偏序。

      这一条实在是太妙了,它将一个前缀和的前缀最小值问题转化为了一个匹配问题。这启示我们在别的地方也能够尝试这么做。

posted @ 2024-09-02 11:49  David_Mercury  阅读(16)  评论(0编辑  收藏  举报