Ideas of Problems in Aug. 2024
\(\text{Luogu P1552 [APIO2012] 派遣}\)
前置芝士:可并堆(左偏树)或 斜堆 或 启发式合并。
本题题意概括为:给定一颗以 \(1\) 为根的树,每个点有权值 \(L_i\),花费 \(C_i\),可以选择一个以某个结点为根的子树,并从其中选出一个点集 \(T\) 满足 \(\sum_{i\in T} C_i \leq M\),那么此次的价值就是这个结点的 \(L_i\times |T|\)。求最大价值。
显然,每个点选择的点集肯定是将子树中点从小到大一直选,直到和大于 \(M\),这样选出来的点集的大小才最大,我们不妨不考虑选点,而是考虑删点,将子树中的点从大到小开始删去,直到和小于等于 \(M\),那么这个可以用大根堆维护。每次加入子树中的点会每次都 \(O(n\log n)\) 操作,由于是子树问题,可以考虑直接把儿子结点的堆合并起来,使用启发式合并,总时间复杂度为 \(O(n\log n)\)。
\(\text{Luogu P4051 [JSOI2007] 字符加密}\)
前置芝士:后缀数组。
本题题意概括:给定字符串 \(S\),将它围成一个环,从不同位置开始读一周可以得到 \(|S|\) 个字符串,将这些字符串从小到大排序后依次输出其最后一个字符。
后缀数组板题。套路地,遇到环就断环为链,将原串复制一遍拼接在其后得到字符串 \(T\),那么这 \(|S|\) 个字符串成功作为 \(T\) 的 \(|S|\) 个后缀的前缀,直接求出 \(T\) 的后缀数组即可,就可以得到这 \(|S|\) 个字符串的排序结果,依次输出即可。
\(\text{Luogu P2852 [USACO06DEC] Milk Patterns G}\)
前置芝士:后缀数组。
题意可概括为给定一个字符串 \(S\) 求出现至少 \(K\) 次的子串的最长长度。
子串问题很容易想到可能使用后缀数组,对字符串后缀排序后,求出 \(\text{height}\) 数组,即相邻排名的后缀的 \(\text{LCP}\),问题可以使用二分或高级数据结构 RMQ 解决。
二分:二分答案,对象是最长长度,判断一个长度 \(l\) 是否合法只需要判断是否 \(\exists i\) 满足 \(\min_{j=i}^{i+K-2} \text{height}_j \geq l\),即是否有一段连续的区间满足他们的 \(\text{LCP}\) 长度大于或等于 \(l\)。
RMQ:可使用线段树或 st 表等,查询区间 \(\text{height}\) 数组最小值。
\(\text{Luogu P4248 [AHOI2013] 差异}\)
前置芝士:后缀数组。
原题式子即为:
显然当 \(n\) 一定时前两项的求和是个常数,等于 \(\frac{1}{2}n(n-1)(n+1)\),后面的 \(\text{LCP}\) 单独处理。显然,这是求字符串任意两个后缀的 \(\text{LCP}\) 之和,所以后缀的顺序无关,可以愉快使用后缀数组。通过后缀数组求出 \(\text{height}\) 数组,即排序后相邻两个后缀的 \(LCP\),则排序后第 \(i\) 个后缀与第 \(j\) 个后缀的 \(\text{LCP}\) 为 \(\min_{k=i}^{k} \text{height}_k\),那么对于求和,首先肯定不能采用 \(O(n^2)\) 枚举后缀起点终点,这样没有优化空间,可以考虑计算每个 \(\text{height}_i\) 对答案的贡献,因为是取区间最小值,每个 \(\text{height}_i\) 只对它作为最小值的区间有贡献,也就是不包含比它小的值的区间,可以使用单调栈维护。
\(\text{Luogu P1944 最长括号匹配}\)
前置芝士:线性 DP。
定义状态 \(f_i\) 表示以 \(S_i\) 结尾的匹配子串最长长度,因为子串要求连续,所以转移很显然由 \(f_{i-1}\) 得到,如果 \(S_i\) 是左小(中)括号,那么显然是失配的。以 \(S_{i - 1}\) 结尾的匹配子串能达到长度 \(f_{i-1}\) 那么要求最长,只需要判断 \(S_{i-f_{i-1}-1}\) 这一位与当前位是否匹配即可。如果匹配,那么 \(f_i\) 可以由前一位的 \(f_{i-1}\) 和 \(f_{i-f_{i-1}-2}\) 拼接得到,如果不匹配,可以证明当前位无法组成匹配子串,感性说明一下:如果不匹配,则不能向开头延伸,因为这一位不匹配,也不能向后减少,因为这样会拆散 \(f_{i-1}\) 匹配的字符串,所以 \(f_i=0\)。
所以状态转移方程为:
\(\text{Codeforces #372 C. Watching Fireworks is Fun}\)
前置芝士:单调队列。
题意简述:
大街被分为 \(n\) 个单位,从左到右标号为 \(1,2,3,\cdots,n\),,初始时间为 1,位置任意,共有 \(m\) 场花火大会,时间为 \(t_i\),举办在 \(a_i\),快乐值为 \(b_i\),每个单位时间可以移动至多 \(D\) 单位,如果在第 \(i\) 场花火大会时位于 \(j\),则可获得快乐值 \(b_i-|a_i-j|\),问最大快乐值。
先考虑朴素 DP,定义状态 \(f_{i,j}\) 表示在第 \(i\) 场花火大会时位置在 \(j\) 的最大快乐值。从上一场花火到这一场至多能移动 \(D \times (t_i-t_{i-1})\) 单位,所以状态转移方程为:
发现对于确定的 \(i,j\),\(b_i-|a_i-j|\) 是个定值,所以提出 \(\max\),只需要求上一场花火的 \(f\) 数组之后区间 RMQ,并且当 \(j\) 分别取 \(1,2,\cdots,n\) 这些区间是向右移动的,所以用单调队列维护 RMQ 即可。

浙公网安备 33010602011771号