刷题杂记 Pt.3
-
-
给定 \([l, r]\),询问满足 \([l', r'] \subset [l, r]\) 的 \([l', r']\) 的价值和。经典题型,几种思路:
-
离线扫描线。移动 \(r\),数据结构内对每个 \(l'\) 维护当前所有 \(r'\) 的价值和(等价于维护历史和),每次做区间和。
-
对每个区间维护前缀和、后缀和,做拼凑。
-
考虑每个数对整体的贡献。
-
-
典型的均摊时间复杂度运算:\(\gcd, \text{bitand}, \text{bitor}\),以及整除、区间覆盖。
-
维护历史和的 Trick:总历史和 \(=\) 当前和 \(\times\) \((\) 当前时间 \(-\) 上次时间 \()\) \(+\) 前历史和。这样我们可以在不支持线段树打标记的情况下维护历史和。
-
-
-
“转化为暴力”型题目。
-
在保持想要的性质不变的前提下,对图进行简化。常见的简化方式是保留图的生成树。这种题的关键是考虑环对路径的影响。类似 Trick 题目:P4151 [WC2011] 最大XOR和路径
-
先分而合:本题对不同种类的连通块分别进行讨论,然后再将他们合在一起。
-
-
-
“子树合并”是树上问题的基本想法。
-
长链剖分一般在合并有关长度时被用来进行优化;这时其实用启发式合并复杂度是一样的(也是 \(O(n \log n)\))。
-
-
-
AC 自动机解决问题的基本思路为:先插入模式串,每次操作文本串,然后对
fail
树做操作。 -
处理树上问题的两个角度:
-
插入时,修改其所有祖先;然后单点询问。
-
插入时单点修改;询问时,查询其子树。
一般来说,方法 2 在实现上是更为简洁的;但方法 1 可能会更好思考。而方法 1 往往能够通过做树上差分变为方法 2。
-
-
虚树思想:将关键点按照 \(dfs\) 序排序后,取相邻两个点的 \(lca\) 就可以得到虚树。
这种题目往往不需要真正建出虚树。如本题,求关键点到根的路径并,可以直接树上差分;以及 P3320 [SDOI2015] 寻宝游戏,求关键点之间的路径总长。
-
-
P3215 [HNOI2011] 括号修复 / [JSOI2011]括号序列
-
线段树没法做区间翻转!只能用文艺平衡树!
-
做数据结构题时,将每一个步骤怎么做想清楚再开写。
-
-
阶梯 Nim + 插板法 + 整体减空白简单容斥 + 简单 DP。。。
-
二分答案 + 拆点建图 + 最大流。
-
-
两个思考角度:考虑修改对每个询问的影响;直接考虑询问。如果你发现无修改情况特别好做,但一旦引入修改就很复杂,不妨从前者想想。
-
“区间 \(\rightarrow\) 二维数点”
-
动态二维数点问题
-
操作类型:平凡情况支持单修区查,做差分后可以支持区修单查。区修区查……可能可以在 KD-Tree 上做。
-
适用数据结构:二维线段树、树状数组套主席树、线段树套平衡树、CDQ 分治、KD-Tree。
-
-
维护历史和的 Trick:总历史和 \(=\) 当前和 \(\times\) \((\) 当前时间 \(-\) 上次时间 \()\) \(+\) 前历史和。(用于不方便线段树打标记的情况。)
这道题中,我们使用了支持历史和的树状数组。实现过程中,我们不用将式子拆开(即分别维护“当前和 \(\times\) 上次时间”、“当前和”、“前历史和”),只需要对每个下标分别维护“当前和”、“上次时间”、“前历史和”三个值,每次在树状数组中更新该下标的时候就顺便改即可。
-
-
- 在树论问题中遇到“换根”操作时,我们可以保持根不变,而是考虑换成的根会让子树范围产生什么变化。类似 Trick 题目:P4689 [Ynoi2016] 这是我自己的发明
-
圆方树好题。
遇到圆方树题目,先考虑树上做法,这样会有助于思考。但也要注意圆方树本身结构的特殊性(比如连通性、圆点根、孤立点……)。
-
实际这道题分析得并不够透彻,但碰巧也做出来了。。。
因为我做的时候忽略了区间 DP 自带的“决策包含性”,即我们不用在每一步把状态划分得那么“完美”,往往来说把一个区间划分为两个就够了。比如此题,如果我们考虑 \(r\) 必须放置的性质,我们只需要找到下一个完全无关、且满足区间性质的区间即可。
-
-
概率 / 期望可以相乘,当且仅当二者互相独立。
-
二维数点问题:本质上实际是三维偏序问题。
算法 / 数据结构 在 / 离线 动 / 静态 修改 & 询问 时间复杂度 空间复杂度 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)\) 本题为典型的二维线段树。
-
-
不要一看到什么“翻转”就想到平衡树——这个题有趣的地方在于它将对序列的“旋转”“翻转”转化为对每个下标的“变化量”的操作。具体怎么变的?你可以推导两个操作分别会对变化量带来什么影响,是系数项的变化还是常数项的变化,然后分开维护,就像维护线段树标记那样。
-
明显的区间 DP。Trick:将两个 DP 数组嵌合在一起使用,当你推当前设出来的 DP 的转移方程时如果遇到困难,不妨再设一个别的。
-
可持久化数据结构 + 树上差分。
-
打破了随机游走期望 DP + 高斯消元的套路,而是用线性性拆解得到简单的递推式。
当然,还有一种从简化高斯消元的角度出发的方法。。。
-
我是脑残,“若干个数异或”这种关键词肯定得想到 线性基 啊。。。
-
特别好的一道题。
-
拆数
第一步转化有两种方法。一种是将数拆解为 \(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\) 的 可重集 数量。一个简单的想法是这么执行背包的循环的:
-
当前已经放入 \(i\) 个 \(111 \cdots\)。
-
当前余数为 \(j\)。
-
新放入的余数为 \(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}\)。
-
-
-
-
用生成树来维护图的连通性。然后再贪心一下,就转为维护其最大生成树了。
-
LCT 维护边信息需要边化点。
-
-
我一开始做这道题时没有看出来这是二分图最大权完美匹配,而是从上下界无源汇最大权可行流推过来的,某种意义上发现了前者为后者的特殊形式。
-
第二分块。
-
分块题,可以先思考只存在整体操作时怎么做。
-
从减小值域的角度入手,即将值域作为复杂度势能函数。
-
在合并以后就不会再分开,想到并查集。不要忘记并查集既有路径压缩又有按秩合并时是 \(O(n)\) 的。
-
卡空间方法:将询问离线,对每一个块单独做。前提是块之间独立,且答案满足可加性。
-
-
P5904 [POI2014] HOT-Hotels 加强版
没有想到简单的树形 DP 方法。。。于是还套了一个点分治。。。
那个树形 DP 的关键在你要大胆设。也是两个 DP 数组配合解决的问题。
然后就是长链剖分,因为这是与长度相关的树形 DP。时间复杂度注意是 \(O(n)\) 没有 \(\log\)。
-
真 · 树套树。
-
这里面在线查询区间第 \(k\) 大,要敏感地想到主席树。
-
然后注意一下路径的分讨即可。
-
-
01 分数规划 + \(O(n)\) 祖先依赖树形 DP。
-
Huffman 式区间 DP(每次合并必须合并相邻 \(k\) 个字符,并生成一个新字符)。有结论:
如果当前区间长度为 \(len\),则最终得到区间长度一定为 \((len-1) \bmod (k-1) + 1\)。
鸽了好久没写(
这里是套题总结。
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:
-
给定若干数,如果其存在能够形成三角形的数,则它们一定在前 \(\log w\) 大的数中出现。
-
如果在给定数列中,最大值能够与剩下的数中的某两个形成三角形,那么最大值一定能与次大值、次次大值形成三角形。
-
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:先尽量贪心放入,再用背包做。
2024.10.21 洛谷NOIP模拟16
-
T2
-
遇到在相同限制条件下末状态相同、初始状态不同的 DP,可以考虑做倒推。
-
遇到初始状态相同,而限制条件不同的 DP,可以试着转化为 1 中的情况。
-
-
T3
关于合法括号序列的 Trick:
-
任意时刻,都有 \(cnt_L \ge cnt_R\),且最终有 \(cnt_L = cnt_R\)。
-
令
(
值为+1
,)
值为-1
,则值每时每刻为正,且最终为 0。
(关于上面两个性质,我一时忘记了在哪些地方有所应用,有机会补过来。)
-
一个长度为 \(2n\) 的括号串合法,当且仅当所有左括号的位置能被 \(1, 3, 5, 7, \dots, 2n − 1\) 偏序。
这一条实在是太妙了,它将一个前缀和的前缀最小值问题转化为了一个匹配问题。这启示我们在别的地方也能够尝试这么做。
-