十月杂题
1.
CF708E Student's Camp
考虑连通,即为存在从上到下的路径。对路径 dp,我们从左上开始走,若能向下直接向下,否则往左或往右直到第一个能下去的位置下去。状态即为 \(f_{i, j, 0 / 1 / 2}\) 表示当前在 \((i, j)\),是从左边 / 上面 / 右边过来的的方案数。转移可以前缀和优化。
2.
洛谷 P10716 简单的字符串问题
判掉 \(k = 1\)。
显然合法的串是 border,先 kmp 建出 fail 树,则合法的是从根下来的链的一段前缀。树上倍增一下,需要检查合法性,即一个串的第 \(k\) 次出现位置。这类似于一个后缀和原串的 LCP,考虑 Z 函数。从小往大枚举长度,先把所有 Z 函数比当前长度小的位置删掉,然后只需要暴力往后找未删除位置即可。并查集维护,这里的复杂度是 \(n \alpha(n)\ln n\) 的。总复杂度一个 \(\log\)。
3.
P5289 皮配
注意到独立性,先把没有限制的统一分两维做掉。如果一个学校的城市存在限制学校,但这个学校本身不限制,则也在这里做掉。然后考虑所有限制,由于值域很小,这里直接暴力 \(\mathcal{O}(mks)\)。然后考虑合并,枚举最后一个 dp 数组,则对于另一边两个的限制分别是一个区间,前缀和一下即可。
4.
P4827 Crash 的文明世界
普通幂转下降幂,得到 \(\binom{dist(i, j)}{k}\) 状物。直接 dp 根据组合意义转移即可。
换根 dp,可以用链式前向星,并将状态记在每条单向边上,采用记忆化搜索的写法,就不用写诡异东西了。
5.
ARC104E Random LIS
直接钦定所有大小关系,只需要求出有多少方案满足之。将值域划分为若干段,设 \(f_{i, j}\) 表示考虑到第 \(i\) 个,处于第 \(j\) 个值域段,每次统一转移位于同一个值域段的即可。
6.
LOJ #6041 事情的相似度
考虑从小往大加入每个 ht,并合并两个集合的过程。我们关注的是在这个过程中,区间 \([l, r]\) 中的后缀什么时候第一次存在两个位于同一个集合中的东西。那么每次合并集合,只需要在小的扔进大的的过程中把扔进去的东西和其前一个和后一个作为关键区间拎出来,最后只需要对所有关键区间和询问区间二维数点即可。
7.
HDU 6566 The Hanged Man
考虑按 dfs 序加点。但是在新点不是上一个点儿子的时候,没法知道祖先的点是否选。因此考虑重链剖分,每次先递归轻儿子,这样就可以状压所有轻链顶的父亲的状态了。
也可以使用点分树。性质是和一个点在原树上相邻的点一定是其点分树上的祖先或子树内的点。因此在点分树上按 dfs 序加点,就可以直接状压所有祖先了。
8.
洛谷 P9839 四暗刻单骑
容易发现和牌只能靠自摸。接下来发现一个人手上的牌如果有用,不管是要自己和还是截对面,那他一定会摸切。因此考虑某个人拿着一张牌一直摸切会发生什么。容易发现这之后要么平了,要么自己赢,要么对面赢。我们将拿着一张牌一直摸切会发生的事记作这张牌的收益。收益的计算只需要考虑这张牌的后两次出现,对着讨论出现位置的奇偶性即可。那么由于玩家的目标在不能赢时是守平,因此当且仅当一个人在对面采取守平时必胜才是必胜。那么可以有平方暴力,就是扫过去然后每个人贪心选取手中收益优的一张保留。如果某个时刻收益产生了则判断胜负。
观察这个过程,发现发生答案判定的时候导致判定的必然不是一个输牌,因若一个人手上有两张输牌,那他一定可以选择输的晚的一张保留。从而只需要关注赢牌与平牌导致的胜负判定。而对于这两种牌玩家一定会选取最早的那一张,并在那个时候取得收益。因此只需要线段树维护每张牌的收益,查询的时候求区间最小值即可。
- 固定的行为模式?尝试考虑。
9.
P6773 命运
对限制容斥,\(f_{i, j}\) 表示 \(i\) 子树中最上的限制飞到了深度为 \(j\) 的祖先的染色方案乘以容斥系数的和。注意到这个东西可以线段树合并优化,只需要合并时实时记一个后缀和。于是做完了。
也可以不容斥,直接 \(f_{i, j}\) 表示当 \(i\) 的祖先中最下的染色边在深度 \(j\) 时子树的方案数。这个东西在叶子的时候需要做区间加。实际上是可以做的,考虑合并时若两个节点都非空,则正常下传标记。否则,因为这里的合并是对位乘,就给非空的那个点打一个区间乘法 tag。当然其他类型的合并(对位加之类)应该也可以这么做。
10.
CF802O April Fool's Problem
费用流建模是容易的,因此具有凸性。考虑 wqs 二分,每次 chk 的时候,考虑从后往前扫 \(a_i\),每次的决策是把这个 \(a_i\) 匹配一个新的 \(b_i\),或者换掉之前的一个 \((a, b)\) 对。可以证明当采取第二种决策时,拆散后用 \(a_i\) 被拆散出来的 \(b\) 仍会是在剩余所有决策中的最优决策。于是只需要用一个 pq 维护所有决策,每次如果堆顶决策的收益小于 \(0\),就做就好了。
11.
CF917D Stranger Trees
将 \(c\) 个大小为 \(a_i\) 的连通块用边连成一棵树的方案数为 \((\sum a_i)^{c - 2}\prod a_i\)。于是直接 dp 最后容斥就好了。使用 product trick,将连通块乘积变为在每个连通块中选出一个点的方案数,就不用记根连通块大小了,总复杂度平方。
12.
P5644 猎人杀
转化为随机开枪,直到打死一个人。显然和原本等价。然后可以想到容斥,钦定一个集合 \(S\) 中的人在 \(1\) 之后死。枚举第一个人死的时间可以列出这种情况的概率:\(\sum\limits_{i = 0}^{\infty}(\frac{S - sum - w_1}{S})^i\frac{w_1}{S}\),其中 \(sum = \sum\limits_{i \in S} w_i\)。容易发现这就是 \(\frac{w_1}{sum + w_1}\)。于是只需要带容斥系数求出凑出 \(sum\) 的方案数。分治 NTT 即可。
-
- (经典?)问题:有向图要求环的方案,利用拆点二分图完美匹配构造。
13.
LOJ #575 不等关系
对大于容斥。被容斥的大于就是小于,因此限制只在未定的大于。对这些东西 dp,\(f_i\) 从前面的被未定的大于号转移,系数只和 \(i - j\) 有关(所有未定之间的段相当于多重组合数,因此系数是阶乘逆),分治 NTT 即可。
14.
P6775 制作菜品
如果将一个菜品视为其所用的两种原料中的一条边,那么不难发现一定存在一种方案使得最终图中不存在环。那么若 \(m \ge n - 1\),则只需要每次选出最小的,如果比 \(k\) 大就减掉 \(k\),否则用当前最大的原料凑够 \(k\) 克。容易发现这是一定合法的。而如果 \(m = n - 2\),则至少会有两个连通块,每个连通块都必须满足 \(\sum d \ge (sz - 1) \times k\),其中 \(sz\) 为该连通块大小。将 \(d_i\) 统一减 \(k\),变成 \(\sum (d_i - k) = -k\)。只需要 01 背包即可。再加 bitset 优化即可通过。
15.
P5327 语言
考虑对每个点算贡献。固定一个点之后,与其能贸易的点,显然是所有经过它的路径的并中的点。动态维护包含某个点集的最小连通块大小是容易的,只需要每次加入 / 删除 \(x\) 时和 dfs 序相邻的两个点取 LCA 较深的点,这个点到 \(x\) 的直链就是这次修改改变的答案。
注意到一条路径经过一点,必要条件是其有至少一个端点在这个点的子树中。于是只需要对每个点 \(x\) 维护所有至少一个端点在其子树中的路径的并(当然,要去掉这些中 LCA 比 \(x\) 深的,这是容易的)。dsu on tree 即可。似乎也可以线段树合并。反正都能过。
- 过一个点的路径一定有端点在其子树中。
16.
CF1515E Phoenix and Computers
连续段 dp。\(f_{i, j}\) 表示加入到 \(i\),有 \(j\) 个相隔 \(\ge 2\) 的连续段的方案数。
- 连续段 dp 中每个数的位置是由合并决定的。类似把原序列从最大值拆开,然后变成子问题。连续段之间实际上是独立的。
-
P4218 珠宝商(字符串专题)
首先对全局,有平凡的 \(\mathcal{O}(n^2)\) 做法, 利用 SAM。然后我们还可以通过点分治做到 \(\mathcal{O}(nm + n \log n)\)。于是我们考虑对点分治的子树大小根号分治。子树大小 \(\ge B\) 的,跑暴力;否则点分治。可以证明这样的复杂度是 \(\mathcal{O}((n + m) \sqrt{n})\) 的。
-
对点分治的子树大小根号分治。
-
“由于无论子树多大,都要跑一遍 \(\mathcal{O}(m)\),太浪费,于是考虑根号分治。”本质还是用手段平衡复杂度。
-(*)
CF1276F Asterisk Strings(字符串专题)
只考虑 \(\texttt{s*t}\) 的情况。可以视为一个前缀的后缀拼上一个后缀的前缀。那么尝试枚举 \(s\),容易发现出现位置相同的 \(s\) 本质相同。也就是 \(\text{endpos}\) 一样的串可以放一起考虑。那么枚举 \(\text{endpos}\),就要求一些后缀一共有多少本质不同子串。
而实际上这就是这些后缀在反串 parent 树上到根路径并的总长度。启发式合并或者线段树维护即可。
- parent 树上的祖先,是自己的全部后缀。因此 SAM 的存储实际上是所有“前缀的后缀”。这在 SA 的笛卡尔树上也是一样的(只不过反过来)。因此一个串的本质不同子串数,就是 parent 树上整棵树的边权和。而 SA 上就是 \(\frac{n(n + 1) / 2}{2} - \sum ht\),因为 \(ht\) 存的就是 parent 树上 dfn 相邻两点的 LCA 深度。这也是为什么 ht 的笛卡尔树可以用于替代 parent 树(即 SAM 的大部分用处)。
-(*)
CF1038F Wrap Around(字符串专题)
\(f_{i, j, k, l}\) 表示填了 \(i\) 个字符,当前在自动机的第 \(j\) 个位置,若初始状态在 \(k\),则现在在 \(l\) 的方案数。转移是 \(\mathcal{O}(1)\) 的,统计答案容易。总复杂度四次方。
- 将需要知道的信息直接放进 dp 状态,就像这样。
17.
CF1416E Split
显然有平方 dp:\(f_{i, j}\) 表示到第 \(i\) 个数,最后一个数是 \(j\) 的最多相同相邻次数。观察转移,发现任何时刻所有 dp 值最多只可能有三种数,而且一定是连续的,而且如果有三种数,最大的最多只有一个。那么再观察这些东西的变化,每一次相当于把最大值赋给所有数,然后那些值为 \(mn + 1\) 的位置会关于 \(a_i / 2\) 这个位置左右翻转。然后如果 \(a_i\) 为偶数,则额外给 \(a_i / 2\) 位置加一。那么就可以拿一个 set 维护所有 \(mn + 1\) 的位置,拿一个 int 维护 \(mn + 2\) 的位置,转移就模拟一下就好了。
- 观察转移。
18.
ABC201F Insertion Sort
首先容易发现每个人最多移动一次。然后考虑那些不动的人。首先他们要构成上升子序列,然后考虑他们对剩下人的限制。设不动的人当中最小的是 \(x\),最大的是 \(y\),那么显然(编号)\(< x\) 的人要么给他扔最前面,要么扔任意位置。比 \(y\) 大的同理。\(\in (x, y)\) 的,就必须使用扔任意位置了。
- 不仅要考虑动的人之中的限制,也要考虑不动的人的限制。要考虑全。
19. (*)
1528F AmShZ Farm
对于合法的 \(a\) 数组,可以转化为计数数组每个位置的前缀和不能超过其下标。那么有经典转化:\(n\) 个位置排成环,并在 \(n + 1\) 位置插入虚点。\(n\) 个人,第 \(i\) 个人会尝试在 \(a_i\) 落座。若不能则往前找到第一个可行位置落座。则合法的充要条件即为虚点无人。
那么有了这个之后合法序列的数量就容易统计了,是 \(\frac{(n + 1)^n}{n + 1}\)。而且从这个转化中,我们也会发现,一个合法序列会对应 \(n\) 个计数数组与之循环同构的非法序列。那么由于我们只关心计数数组(因为算 \(b\) 的答案只用到计数数组),因此不妨先把所有序列的答案都统计上,最后再除以 \(n + 1\)。
那么接下来就可以考虑对每个元素算贡献。考虑一个元素 \(x\) 对答案的贡献,即为 \(\sum\limits_{c = 0}^n\binom{n}{c}n^{n - c}c^k\)(第二个幂的底数是 \(n\) 是因为剩下的数里不能有 \(x\))。由于所有元素本质相同,所以这个要乘 \(n + 1\)。而由于这里算了非法序列,最后又要在除掉 \(n + 1\),因此两项抵消,之后不再考虑。
接下来推式子:
到这里就可以直接算了,只需要一行的第二类斯特林数。而行第二类斯特林数是好求的,只需要根据普通幂转下降幂的式子二项式反演即可:
直接 NTT,复杂度 \(\mathcal{O}(k \log k)\)。
- 经典接链为环,而环上由于元素的对称性,就会有美妙的事情。
20. (*)
ARC120F Wine Thief
首先容易想到对每个元素算贡献。但是钦定了一个元素选之后,剩下的不太好做。那么,拼成环。
设 \(f(n, k)\) 为 \(n\) 个点的环上,大小为 \(k\) 的独立集有多少个(再设 \(g(n, k)\) 为序列)。那么由于环上每个元素的对称性,每个数被选到的概率都是 \(\frac{k}{n}\)。也就是说每个点被选中的方案数都是 \(\frac{kf(n, k)}{n}\)。但是这样我们少算了方案,少算的方案是链的两端都被选的那些。而扣掉两端之后,发现剩下的是一个序列上的子问题!而这个子问题的方案数(\(g(n, k)\))又恰好就是 \(a_1, a_n\) 的系数。那么我们直接向子问题用同样的方法递归计算即可。终止条件是当前子问题规模 \(\le 3\),此时的计算是容易的。
关于 \(f, g\) 的计算,有 \(g(n, k) = \binom{n + 1 - k}{k}\),\(f(n, k) = g(n - 1, k) + g(n - 3, k - 1)\)(通过讨论第一个元素)。那么整个题复杂度就是 \(\mathcal{O}(n)\)。
-
接链为环,利用环的对称性考虑。
-
发现了子问题并递归。
21.
1523F Favorite Game
容易发现,如果当前在传送塔,那么位置是不重要的。容易写出 dp:\(f_{S, i}\) 表示解锁了 \(S\) 集合的塔,并完成 \(i\) 个任务的最小时间。但是这个 dp 不能考虑位置。
容易发现,如果当前在目标点,那么时间是可以知道的。容易写出 dp:\(g_{S, i}\) 表示解锁了 \(S\) 集合的塔,当前在第 \(i\) 个目标点,最多能完成几个任务。但是这个 dp,看起来不太好转移。
那么我们直接把这两个 dp 一起做。如果当前在传送塔,我们采用 \(f\)。如果当前在目标点,我们采用 \(g\)。
然后就可以用这两个 dp 互相转移。于是就做完了。
- dp 可以不只有一个。此题中可能是由于两个 dp 互补的性质。
22.
ARC121F Logical Operations on Tree
考虑 0 和 1 的个数,我们希望 0 的个数归零。那么先把 0 连通块缩起来。接下来要减少 0,必须用 0 去撞 or 边才能消掉。那这样就发现 and 边是不是没啥用,那么也全部缩起来。那么此时就会发现,如果我们把所有 and 边先缩起来,那么合法当且仅当此时树中存在一个 1。证明是显然的。然后就可以直接树形 dp 了。
- \((\neg q \rightarrow \neg p) \rightarrow (p \rightarrow q)\)。
23.
CF1534G A New Beginning
显然先转曼哈顿,那么种植只会在某个土豆的横坐标。平凡的 dp 是 \(f_{i, j}\) 表示到第 \(i\) 个土豆的横坐标,纵坐标在 \(j\) 时的最小代价。转移是每个点变为邻域的 \(\min\),最后整体加(平移的)绝对值函数。那么显然可以 slope trick,每个点变为 \(d\) 邻域 \(\min\) 等价于水平线左边的转折点统一左移 \(d\),右边的统一右移 \(d\),整体加绝对值相当于在某个横坐标插入两个转折点。fhqtreap开两个 pq 分别维护水平线左右的转折点,然后额外维护一下水平线的值即可。这些都是容易的,总复杂度 \(\mathcal{O}(n \log n)\)。
24.
CF1481E Sorting Books
先缩连续段。考虑对不动的东西 dp。发现不动的颜色对应的出现位置区间一定不会交。而特殊情况只有最后一种不动的颜色,它可以选择一个后缀不动,而让这个颜色前面的出现都往后动。前面的 dp 是容易的,后面的稍微讨论一下就可以了。总复杂度 \(\mathcal{O}(n)\)。
25.
CF1517F Reunion
转化为答案 \(\ge i\) 的概率,还是不好做。但是反过来考虑,答案 \(< i\) 的概率。这相当于要求每个点的 \(i\) 邻域内至少要有一个黑点。相当于选择黑点覆盖所有点。于是就可以直接 dp 了,\(f_{i, j}, g_{i, j}\) 表示若 \(i\) 子树完全覆盖,向上延伸 \(j\) 的概率,或者若没有完全覆盖,最深的未覆盖点在 \(j\) 的概率。这样直接暴力可能是四次方,但是容易用前缀和优化到三次。
26.
CF1517G Starry Night Camping
考虑将点按照横纵坐标的奇偶性分成四类,则容易发现一个非法的图案一定是一个经过四种点的长度为四的路径。于是最小割即可。
- 网络流中,尝试考虑对点分类。
27.
CF1495F Squares
可以考虑将每个点连向前面第一个比它大的点,这样每个点的行为要么是进入子树,要么是直接跳过子树。那么所有的限制就相当于是说它们的祖先都不能采用跳过子树的决策。那么剩下的东西就应该是简单的了。
还有另一种做法。考虑询问时我们要求的是若干 \((x \rightarrow y)\) 的最短路的和,因此可以把所有询问的最短路离线下来分别求。这个就可以按右端点扫描线,由于所有跳过构成的区间都是不交或包含,因此对于一个右端点,只需要枚举所有跳到它的位置,然后若这个地方当前维护的最短路比直接跳过来劣,就直接跳过来,并更新前面所有点的最短路。
-
各种连边方法都要试一试,尽管看起来可能没啥道理。
-
第二种做法:离线处理。
28.
CF1392H ZS Shuffle Cards
考虑 \(\min - \max\) 容斥计算 \(n\) 张牌中最晚抽出的轮数。枚举 \(|S|\),相当于抽到 \(S\) 中的牌就下班。而一轮结束时有 \(\frac{|S|}{m + |S|}\) 的概率是抽到 \(|S|\) 中牌,因此期望要 \(\frac{|S| + m}{|S|}\) 这么多轮才能下班。求出了期望最大轮数之后只需要再乘以一轮的期望时间即可。这是容易计算的。
29.
CF771E Bear and Rectangular Strips
考虑按顺序取出最后方案中的每个矩形。按照横坐标的起始位置升序来取。
设 \(f_{i, j}\) 表示第一行的前 \(i\) 列,第二行的前 \(j\) 列的答案,\(g_i = f_{i, i}\),那么由我们刚才的取法,不难发现只有 \(f_{i, j} \le g_{\min\{ i, j \}} + 1\) 的 \(f_{i, j}\) 是有用的。而且对于一些都符合这个条件的 \(f_{i, j}\),我们也只需要保留 \(\max \{ i, j \}\) 最小的那个。那么这样的话,总状态数就只有 \(\mathcal{O}(n)\) 了,那么只需要对每个状态直接转移就好了。
- 钦定顺序,不考虑无用状态。
30.(*)
CF1450G Cummunism
可以把合并的过程视为一棵树。那么首先容易想到直接状压 \(f_{S}\) 表示 \(S\) 是否能归为同一颜色(注意,并不是说真的就要都是同一种颜色)。转移也很简单,一种是枚举一种新的颜色变过去,要求变过去之后的集合是可变的(满足题目中给出的条件),相当于给这个集合中的子树找一个根;另一种是枚举分成两个子集,如果两个子集的 \(f\) 都是 \(1\),则 \(f_S\) 也为 \(1\),相当于把两个子树集合拼起来。这样的复杂度是 \(3^{\Sigma}\) 的,过不去。
考虑怎样的转移是没有用的。会发现若合并的两个集合在原序列上对应的区间有交,则这样的转移是无用的。证明就考虑左边那个区间最右的子树和右边那个区间最左的子树,它们的区间是交的。那么就可以把两棵子树中的一棵合并到另一棵上,显然这样不会改变合法性,也就是新的子树仍然满足题目中的条件。于是有了这个条件之后,这一种转移就也是 \(\mathcal{O}(\Sigma2^{\Sigma})\) 的了。
- 考虑怎样的转移是无效的。
31.
ABC209E Shiritori
每个字符串视为前三个字符和后三个字符之间的建边,直接有向图博弈即可。
32.
CF1034D Intervals of Intervals
二分答案来求前 \(k\) 大和。区间区间并的问题考虑染色,扫描线右端点 \(i\),并将区间 \([l_i, r_i]\) 染上颜色 \(i\),那么 \([j, i]\) 的区间并就相当于有多少点的颜色 \(\ge j\)。先跑一遍染色求出加入每个右端点之后每个颜色的数量会如何变化,然后 check 的时候枚举右端点,容易发现最大合法的左端点 \(j\) 也是单调的。只需要每次修改的时候考虑对当前左端点答案和前 \(j - 1\) 个区间的答案和的影响即可。
33.
AGC021F Trinity
考虑按列 dp。\(f_{i, j}\) 表示考虑了前 \(i\) 列,已经有 \(j\) 个非空行的方案数。接下来考虑转移。考虑新的这一列中的 \(B_i, C_i\) 是否取在原有的行当中。设 \(j \rightarrow k\),那么分三种情况讨论:
-
\(B_i\) 和 \(C_i\) 都在新选的行中。这种情况就是 \(\binom{k}{k - j}\)。
-
两个都不在新选的行中。那么考虑从 \(k\) 行中选出 \(k - j + 2\) 行,其中中间的 \(j\) 行作为新选的,第一行和最后一行作为 \(B\) 和 \(C\),那么这种情况的方案就是 \(\binom{k}{k - j + 2}\)。
-
有一个在。和上一种类似,这是 \(2\binom{k}{k - j + 1}\)。
三种加起来,一共是 \(\binom{k + 2}{k - j + 2}\)。NTT 优化即可。
34.
LOJ #6406 绿宝石之岛
按照一颗宝石出现的天数区分宝石,通过感性理解(每天每颗宝石以相等的概率分裂)或者推式子证明可以发现所有的终态的出现概率是相等的。因此考虑从高往低 dp,\(f_{i, j}\) 表示考虑了最高的 \(i\) 层,一共用了 \(j\) 颗宝石的方案数,以及 \(g_{i, j}\) 表示此时所有方案的前 \(r\) 大和的和。那么转移就是容易的。最后只需要用所有前 \(r\) 大和的和除以总方案数即可。
-
所有终态出现概率相同。
-
按照值域从高往低 dp。
35.
P3643 划艇
先将值域离散化,\(f_{i, j}\) 表示前 \(i\) 个学校,最后一个学校在第 \(j\) 段的方案数。转移考虑枚举最后一个和这个学校不在同一段的学校,从它的 \(0\) 到 \(j - 1\) 转移过来。中间的东西可能有范围不包括这一段的,让他们填 \(0\) 就好。剩下的系数都可以预处理,总复杂度三次方。
36.
AT_joisc2015_f Keys
先离散化时间。我们希望最小化开门时间,那么考虑什么时候一段时间会产生贡献。发现当且仅当这段时间的开头是没有钥匙的出门或者结尾是没有钥匙的进门时,这段时间会产生贡献。那么根据这个关系在人之间建边,现在就是选择不给一个人钥匙会产生代价,但是一条边连接的两个人如果都没有钥匙则这条边的代价只产生一次。直接做看起来没法做,但是观察到图是一堆链,于是只需要对每条链分别 dp 就可以了。
-
拆开贡献。
-
观察。
37.
HDU 6157 The Karting
还是观察,考察每个路段的贡献次数。发现只要相邻两个路段的贡献次数不超过 \(1\),我们都可以构造合法的路径。而实际上每次贡献变化,就相当于使用了关键点。成对的贡献 \(+ / - 1\) 可以视为括号的匹配,则一次匹配会产生 \(d_0\) 的收益。于是可以 dp,\(f_{i, j, k}\) 表示当前在 \(i\),贡献次数为 \(j\),用了 \(k\) 个关键点的最大收益。每次转移是新开一个左括号,或者用一个右括号,或者在这个地方空放一个关键点。其中最后一种转移要求此时的贡献不为 \(0\)。直接做就好了。
38.
LOJ #521 绯色 IOI(抵达)
题目要求相当于形成基环树森林。但是由于这里不可能有长度 \(> 2\) 的环,也不能有自环,因此所有环长只能为 \(2\),也就是全树分成若干组两两相邻的匹配。而为了保证这个匹配,点与点的权值之间会自然形成一些偏序关系。于是只需要从小到大枚举权值,每次选出最小的能用的编号来放当前的权值即可。
39.
P6847 魔法树
\(f_{i, j}\) 表示 \(i\) 子树,父边在 \(j\) 时刻断掉的最大收益。转移可以直接线段树合并优化,一个 \(\log\)。
但是也可以将状态定义为前缀,这样就是单调的了。我们维护 dp 值的差分,这样两棵子树合并就是对位相加。加入自己的贡献时相当于单点修改,然后扔掉这个点后面的一段,然后再单调修改。这个暴力做就好了。使用启发式合并,总复杂度两个 \(\log\)。
- 对于(单调的)dp,尝试维护差分。
40.
CF573D Bear and Cavalry
先两边排序,然后如果没有限制,肯定是大的匹配大的最优。但是有了限制,但是我们也可以通过调整法证明不会存在 \((i, i \pm 3)\) 这样的匹配。因为设匹配 \((i, j)(|j - i| \ge 3)\),由于 \(|j - i| \ge 3\),必然有至少三条线和 \((i, j)\) 相交。依次用这三条线尝试和 \((i, j)\) 调整,发现不能调整的情况必然是碰到了 \(i\) 对应的 \(j\) 侧点 \(x\),要么是碰到了 \(j\) 对应的 \(i\) 侧点 \(y\)。而再来第三条的时候,无论如何这个时候肯定都可以换了。于是匹配的距离不会很远。
设 \(f_i\) 表示前 \(i\) 个的最优答案,那么更进一步的,我们也可以通过调整法证明 \(f_i\) 只会从 \(f_{i - 1}, f_{i - 2}, f_{i - 3}\) 转移来。于是只需要把转移写成矩阵的形式,跑 ddp 就好了。
- 调整。
41.(*)
CF1476F Lanterns
考虑 dp,\(f_i\) 表示前 \(i\) 个点,最远能连续覆盖到多远的前缀。那么转移分几种:
-
往右倒。要求 \(f_{i - 1} \ge i\)。\(f_i = \max \{ f_{i - 1}, i + p_i \}\)。
-
往左倒。此时,我们找到最小的 \(j\) 满足 \(f_j \ge i - p_i - 1\),转移就是 \(f_i \leftarrow \max \{ i - 1, \max\limits_{k = j + 1}^{i - 1} \{ k + p_k \} \}\)。如果找不到,那么开摆。
-
开摆。\(f_i = f_{i - 1}\)。
构造方案只需要根据转移来就好了。
- 挺灵活的。

浙公网安备 33010602011771号