专栏文章

dp

算法·理论参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mip514m9
此快照首次捕获于
2025/12/03 06:16
3 个月前
此快照最后确认于
2025/12/03 06:16
3 个月前
查看原文
一些笔者最近做过的 dp 好(?)题。

THUPC2025 决赛 I'm here

题解 TBD。

THUPC2023 决赛 喵了个喵 III

题解 TBD。

Flower's Land

不太常规的树上背包?
首先考虑点分治,转化为对每个点 ii,求出若根 rrii 的路径必须选的答案。
发现对于点 ii 的答案可以分成两部分:iirr 的路径上的左兄弟的子树以及 ii 的儿子的子树,和 iirr 的路径上的右兄弟的子树。将这两个背包进行卷积,由于只用算单点值,对于每个点可以 O(k)O(k) 算出。
问题在于如何快速求出这两个背包。我们发现前者是出栈 dfs 序的一个前缀,后者是入栈 dfs 序的一个后缀。两者求法类似,以前者为例:按照出栈 dfs 序从前往后扫,当前扫到点 ss,若选 ss,则可以根据 s1s-1 处的值转移;若不选 ss,则 ss 的子树都不能选,可以根据 ssizss-siz_s 处的值转移。
两部分的时间复杂度均为 O(nk)O(nk),加上点分治后总时间复杂度为 O(nklogn)O(nk\log n)

20250524 联考 T2

比较简单的一个题。
假设已经知道了每个点的度数,考虑如果判断可能的最大匹配是多少。
显然最大值是两侧度数非零点的数量的 min\min。最小值考虑使用 hall 定理,最大匹配为 min{nS+N(S)}\min\{n-|S|+|N(S)|\}。不难发现一定是取左边度数最小的一些点作为 S|S|,右边度数最大的一些点作为 N(S)|N(S)|,给定的 S|S|N(S)|N(S)| 可行当且仅当 S|S| 内部点的度数之和 N(S)\leq |N(S)| 内部点的度数之和(因为可以有重边)。直接对两侧做 dp 即可,dpi,j,k,u,wdp_{i,j,k,u,w} 表示考虑了前 ii 个点,度数之和为 jj,钦定选了 kk 个点,这 kk 个点度数之和为 uu,前 ii 个点中一共有 ww 个度数非零的点。时间复杂度 O(n6)O(n^6)

CCPC Final 2024 M 尾声之下

DAG 容斥在非集合幂级数上的应用。
不难发现一个集合可行当且仅当她是一个 SCC。考虑使用类似 SCC 子图计数的 DAG 容斥。选定若干入度为 00 的 SCC,显然所在区间不交。首尾与两个 SCC 之间可能会连出一些边,一个 SCC 所在区间的内部也可能会连出一些边。
我们设 dpl,r,l,rdp_{l,r,l',r'} 表示用了 [l,r][l,r] 内的点,l,rl,r 必须选,点构成 SCC,并且选的每个点的 [ai,bi][a_i,b_i] 构成的区间都在 [l,r][l',r'] 内,此时的方案数。辅助数组 dpl,r,l,rdp'_{l,r,l',r'} 定义类似,只是不保证所有点构成一个 SCC,而是由若干入度为 00 的 SCC 拼接而成(不一定首尾相接),每有一个就乘上一个容斥系数 1-1,相邻 SCC 之间可以夹着一些东西,llrr 所在 SCC 必然没有入度。
直接实现时间复杂度为 O(n6)O(n^6),但是这样做有一个问题:没有考虑一个 SCC 向其所在区间内部的更小的 SCC 连边。为了消除这类边的影响,我们引入一个函数 ff 满足:
fi+1,i=1f_{i+1,i}=1
1lrn,l1=s1<s2<...<sk=r+1,1<i<k,lasi,bsirfsi+1,si+11=1\forall 1\leq l\leq r\leq n, \sum_{l-1=s_1<s_2<...<s_k=r+1,\forall 1<i<k, l\leq a_{s_i}, b_{s_i}\leq r}\prod f_{s_i+1,s_{i+1}-1}=1
按照区间从小到大扫,可以 O(n4)O(n^4)O(n3)O(n^3) 算出 ff,这里不是时间复杂度瓶颈。
改变一下 dpdpdpdp' 数组的定义:选择一个合法点集 SS 时,其对答案的贡献从 11 改为对于所有 SS 内标号相邻的点 u,vu,v(一共有 S1|S|-1 对),fu+1,v1f_{u+1,v-1} 之积。改完之后我们发现仍然可以以同样的方法计算这两个 dp 数组的值。对于一个 SCC 内标号相邻的两点 u,vu,v,该 SCC 可以向 [u+1,v1][u+1,v-1] 内的点连边,其总贡献就是上面的那个式子,永远为 11

20250603 联考 T3

比较常规,dp 基本功题,不过好像爆标了?(没看题解,不知道题解是什么做法)
第一问是 BJWC 倒数第二场 T1,相信大家稍微想想都会做。
我们发现我们第一问的 slope trick 优化 dp 的流程相当于是解决如下问题:维护一个集合 SS,初始为空。按 bib_i 从小到大排好序后,从前往后扫,每次先执行 bib_i 步若 SS 不为空则从 SS 中选择一个数并将其减 11,减到 00 后就扔出集合。然后将 aia_i 加入集合。最后还可以再执行任意多步上述减 11 操作。f(a,b,k)f(a,b,k) 即为删去 kk 个数最少需要多少步。显然每次贪心地让最小的数减 11 是最优的。
当确定 aa 时没有一个简洁形式的答案表示 f(a,b,k)f(a,b,k)。于是我们考虑直接将贪心过程压进 dp:依旧从前往后扫,每往集合中加入一个数时钦定其是否会被扔掉。我们需要贪心地去钦定:若当前加入的数不小于集合中一个未被钦定的数,则这个数必须不能被钦定;若当前加入的数小于集合中的一个被钦定的数,则这个数必须被钦定。否则会重复计算。于是我们设计出如下状态:dpi,j,k,u,wdp_{i,j,k,u,w} 表示考虑了前 ii 个数,钦定了 jj 个,当前被钦定的数之和为 kk,最大的为 uu,未被钦定的最小的数为 ww。转移时枚举当前 aia_i,枚举其是否被钦定,时间复杂度为 O(n3V4)O(n^3V^4),使用前缀和优化可做到 O(n3V3)O(n^3V^3)
upd:感觉可以做到 O(n3V2)O(n^3V^2),不过只是口胡,没有写,不知道有没有假。

2023-2024 集训队互测 Round 5 T2 栞

木柜子乐队好评
题目比较简单。
首先考虑将 qq 划分成 kk 个上升子段,然后将每个上升子段打乱得到原排列 pp。我们考虑怎样才是合法的。对于一个确定的 pp 我们有如下贪心过程:若 k=1k=1 则将排列排序并退出,否则取出其前 nk+1n-k+1 个数并排序,找到其最小的前缀满足其中所有数在 pp 中出现的位置也是一个前缀,取出这个前缀作为第一段并递归到 k1k-1
考虑 dp:令 dpi,jdp_{i,j} 表示使用了 qq 中的前 ii 个数,划分成了 jj 段的答案。这样做我们发现 dpi,jdp_{i,j} 会对之后的数有限制。具体地,如果 qq 中第 uu 段结尾的数为 enduend_u,那么要求 pp[i+1,nk+u][i+1,n-k+u] 中的数全部 >endu>end_u(否则与前面所述的贪心过程矛盾)。我们发现若当前剩余段的长度不必全都是 11(即 nk+j>i+1n-k+j>i+1),则下一段(第 j+1j+1 段)结尾的数必然大于第 jj 段结尾的数。也就是说,enduend_u 单调递增,因此只用考虑第 jj 段带来的限制。我们枚举下一个 qq 上的单增段,设其长度为 lenlen,共 xx 个数比 enduend_u 小。若 x=0x=0,则其贡献为长度为 lenlen 且【不存在前缀是排列】的排列个数,预处理即可;若 x>0x>0,则贡献非零当且仅当 x=1x=1 且当前段为 [i+1,nk+j][i+1,n-k+j],其贡献就是一个阶乘。

未完待续
笔者快退役了,估计续不了了

评论

0 条评论,欢迎与作者交流。

正在加载评论...