2025.1.13 动态规划
JOISC 2023 Day3 合唱
首先这种类构造问题先转换成判断性的问题,考虑怎么判断一个序列是否能被划分为 \(\le k\) 个部分。
一个贪心是每次找到第一个 B,然后将其前面所有 A 和后面同样数量的 B 划成一组。
此时你就可以发现如果将 A 当作向右走,B 当作向上走,那么按这种贪心策略,每次碰到 B 就向上直到顶然后反弹,只要能拐 \(k\) 次那就合法。

令 \(w(l,r)\) 表示 \(l\) 到 \(r\) 中能容下如上图中的一个三角形至少需要交换多少次,容易发现这个东西满足四边形不等式,wqs 二分。
内部可以使用斜率优化做,推一推式子就行了。
Watching Cowflix P
为什么我一看到这个题就感觉很凸。
首先答案上界为 \(n+k\),因此连通块数目最多为 \(\frac{n+k}{k+1}\)。
考虑根号分治。
对于 \(k=1,2,\dots,B\),直接 \(\text O(n)\) dp,然后再跑 \(\text O(\frac{n^2}{B})\) 的树型 dp 求出连通块数量为 \(1,2,\dots,\dfrac{n}{B}\) 时连通块点数总和的最小值。
[JOIST 2023] 议会
发现会改变的只有值为 \(\lfloor\frac{n}{2}\rfloor\) 与 \(\lfloor\frac{n}{2}\rfloor + 1\) 的。前者只要主副议长有一个就行,后者需要两者皆是。
枚举主议长,就可以求出那些点在副议长选择时会减少,使用一个类高位前缀和的东西预处理出来每个集合对应的值最大和次大的议员即可。
[JOIST 2023] JOI 国的节日 2
这种题考到了怎么能做得出来啊?
首先发现假贪心是按左端点排序,真贪心是按右端点排序。
容斥,用总方案减去合法方案,总方案为 \((2n-1)\times(2n-3)\times,\dots,\times ((2n-1) \mod 2)\)。
问题就出在怎么求出真假贪心结果一样的情况。
由于数量一样考虑两者一起 dp,接下来我们将只有真贪心选择的区间称为红区间,只有假贪心选择的称为蓝区间,两者同时选择成为紫区间,两者同时没选称为黑区间。
根据贪心策略,显然的有如下性质:
- 两相邻红区间的右端点之间无完整区间。
- 两相邻蓝区间的左端点之间无完整区间。
每次添加区间是枚举右端点位于两红色区间右端点之间的黑区间,此时可以发现蓝区间还对黑区间的左端点具有限制,因此还要再开一维表示能插入黑区间左端点的位置数,然后还要记录一下最后一次放的是否是紫区间。
具体实现就不细讲啦,这样做的复杂度是 \(\text O(n^3)\),因为每次转移时要枚举黑区间个数。
我们发现主要限制就在于黑区间的左端点限制不好处理,考虑从后往前填区间,此时你就发现右端点没有任何限制了,因为合法的黑区间左端点必定在红区间内。
令 \(dp_{i, 0/1}\) 表示已经从后往前插入了 \(i\) 个区间,并且最后依次是否是紫区间。
这里给出 \(0\to0\) 的转移:
其中 \((2i-2+j-1)^{\underline{j}}\) 是插入 \(j\) 个黑区间的方案数,\((j+1)(j+2)\) 是计算分割点将\(j+3\) 个区间的左端点分成 \(3\) 段的方案数,可以结合下图理解。


阿巴阿巴就这样吧,我太菜了。
[AGC039E] Pairing Points
关键问题在于状态设计即子问题划分方法。
初步思考发现这东西是初始一条边,接着有许多跨越这条边两端的边,每个边的两端各对应着一个区间,在该区间内继续划分。发现只有第一条边要考虑两个端点,所以直接钦定第一条边连了 \(1\) 号点,令 \(dp_{l,r,i}\) 表示处理 \([l,r]\) 这个区间并且其中 \(i\) 号节点是连向了区间外部的那个点的方案数。
转移也有点讲究,枚举最外侧的一条边覆盖的两个区间 \([l,L],[R,r]\),然后缩成 \(dp_{L+1,R-1,i}\) 继续做,加一点优化就很容易达到 \(\text O(n^6)\),带个 \(\frac{1}{720}\) 的常数,随便过。
[CF1060F]Shrinking Tree
曾经写过的一道题,当时好像一直没太理解透彻。
对于每个点作为根节点做一遍树型 dp,接下来考虑一下子节点 \(x\) 怎么合并到 \(u\)。
假设 \((u,x)\) 这条边是当前 \(u\) 这颗子树与 \(x\) 中第 \(i\) 个合并的,那么 \(i\) 之前 \(x\) 内的合并都与最终留下的节点是否是 \(u\) 没有任何关系,而合并之后相当于把 \(x\) 的所有子树接到了 \(u\)。
令 \(dp_{u,i}\) 表示只考虑后 \(i\) 次操作对编号的影响,最终剩下根节点的边的排列数。\(g_{x,i}\) 表示 \(u\) 点加上 \(x\) 这棵子树构成的树中只考虑后 \(i\) 次操作对编号的影响,最终剩下根节点的边的排列数。
先来考虑 \(g\) 怎么转移,令 \((u,x)\) 在倒数第 \(j\) 个被删:
- 若 \(j \le i\),\(g_i \gets g_i + \frac{dp_{x,j-1}}{2}\),因为此时编号已经开始需要考虑了,所以在倒数第 \(j\) 位一定要保留 \(u\),而剩余 \(j-1\) 个相当于 \(x\) 中子树被合到 \(u\) 上,跟原来是一模一样的。
- 若 \(j > i\),\(g_i \gets g_i + dp_{x,i}\),在倒数 \(i\) 之前不需要考虑编号,在倒数第 \(i\) 时 \(x\) 已经被合掉了,因此方案数就为 \(dp_{x,i}\)。
然后考虑合并 \(g\) 与 \(dp_u\):$dp_{u,i+j}\gets dp_{u,i}g_{u,j}\binom{i+j}{i}\binom{siz_u+siz_g-i-j-1}{siz_u-i-1} $。

浙公网安备 33010602011771号