动态规划
模板
lamentropetion
---
展开
-
2023年浙大城市学院新生程序设计竞赛(同步赛)G
不难想象其实就是操作结点的子树和该点连通的黑色连通块的所有结点,对这些结点会有影响。首先想法非常单一,一定是去枚举操作点,然后看它染白和不染的价值差值。黑色连通块容易用树形dp求,然后就是操作点到最近白色祖先距离怎么求。那么差值其实就是黑色连通块大小 * 操作点到最近的白色祖先的距离。也就是说,把一个黑色结点染白之后,对哪些结点的价值会影响。dfs即可,记录上次的白色结点是什么即可。原创 2023-12-23 23:45:17 · 868 阅读 · 1 评论 -
【计数DP】牛客小白月赛19
然后看影响决策的因素:两边的火焰情况,那就 dp[i][0/1][0/1]表示 前 i 个,该位有无火焰,该位右边有无火焰的方案数。然后状态设计,先设 dp[i]首先做法一定是计数 dp。这样设状态也可以算贡献。然后一定就是分类讨论了。原创 2023-12-23 23:24:08 · 746 阅读 · 0 评论 -
【01分数规划】ABC324F
首先看到这个形式很容易想到 01 分数规划,即去二分答案,然后就是转化成 是否存在一个路径使得 sigma b - mid * sigma c >= 0。显然只需要改变一下边权,跑一遍最长路即可。原创 2023-12-14 01:30:10 · 538 阅读 · 0 评论 -
【计数DP】CF1794D
所以还剩下 n - (sum - j) 个位置,也就是说,在 n - (sum - j) 个位置中选 y 个位置,那就是 C(n - (sum - j), y)问题就是出在这里,我不知道怎么求组合数,一心想着对于指数求可重集排列,但是这么多的指数的个数是很难维护的。然后就是考虑转移,这种计数类的dp在转移的时候都是考虑多一格会多出多少贡献,贡献一般由组合数求出。前缀已经选了 j 个底数,设前缀的个数和为 sum,那么前缀有 sum - j 个数作为指数。设多出来那一格的数为 x, 它的个数为 y。原创 2023-10-25 01:08:24 · 384 阅读 · 0 评论 -
【强连通+背包】CF1763E
那么用哪些多大的强连通连接在一起就用背包处理一下就好了,因为要让节点数尽可能少,代价就是节点数,价值就是每个团的点对数,即x * (x - 1) / 2。然后,因为在这个前提上,要让单向节点数尽可能多,那就考虑将这些强连通分量用有向边连接。首先,先考虑第一个条件,要保证是p个节点互相到达且节点数最少,一定是个强连通,把背包的方案求出来之后直接计算贡献即可,具体看代码。然后背包完之后考虑第二问,求单向点数。原创 2023-10-24 22:41:38 · 210 阅读 · 0 评论 -
【换根DP】CF1882 D
然后就可以直接换根了,首先考虑树形DP,设dp[u] 为 把 u 子树染成同一种颜色的最小代价。首先观察到,先对儿子一定比先对父亲操作来的代价小,因此考虑先对儿子操作,再对父亲操作。那么根据刚刚的先操作儿子,转移方程为。然后换根就正常换就好了。原创 2023-10-21 16:20:41 · 189 阅读 · 0 评论 -
(枚举 + 树上倍增)Codeforces Round 900 (Div. 3) G
首先,目标值和结点权值是直接联系的,最值不可能直接贪心,一定是考虑去枚举一些东西,依靠这种枚举可以遍历所有的有效情况,关于怎么跳其实可以参考树上倍增往上跳的跳法,记录一个数组指向下一个结点,在dfs上维护即可,有点像在树链上DP。如果考虑在链上枚举,如果前缀或值不变,那么这样的枚举是无效的,我们直接考虑跳着枚举,只枚举所有。注意到一条路径上的前缀或值不会超过 logV个,因此考虑枚举前缀或值。如果去直接在链上枚举的话, 复杂度是O(nq),肯定不行。关于每次跳使前缀或值变化的最深的点,我是这样理解的。原创 2023-10-03 23:23:14 · 365 阅读 · 0 评论 -
【暴力DP】CF1409 F
首先有个很明显的结论是:替换的字符一定是那两个字符之一。为了计算贡献,需要把前缀 t1 的数量也放进状态里。那么替换成哪个字符贡献更大不确定,因此考虑DP。因为有操作次数限制,直接把操作放进状态里。然后就暴力分类讨论转移就好了。原创 2023-09-23 01:16:55 · 239 阅读 · 0 评论 -
【期望+状压DP】 2021 CCPC G
注意到在转移过程中需要用到用了哪辆车的两点之间的最短路,因此我们考虑预处理这个最短路,这个就类似于分层图的思想搞一搞就好了。设 dp[x][st] 为 当前处于 x 结点上,且经过的结点状态为 st 的最小期望路径长度。要求最小的期望长度,我们可以遍历所有可能的路径,统计这些路径的期望长度的最小值即可。可能关于期望的状压DP用记忆化搜索会好处理一点(?这里很经典的处理方式是状压DP。注意到 k 的范围是18,可以考虑状压。这里的状压DP我们用记忆化搜索解决。原创 2023-09-23 00:05:12 · 243 阅读 · 0 评论 -
【DP】CF Edu 21 E
当只有w = 1的物品和w = 2的物品时,考虑贪心地把物品按价值排序,然后选。就是一个 N为1e5,M为3e5的背包问题,不过特殊条件是 w <= 3。这个非常的正确,然后加上w = 3的直接枚举即可。我们去从最简单的情况开始考虑。原创 2023-09-03 16:36:56 · 289 阅读 · 0 评论 -
【组合计数 or 树DP】2021 icpc 上海 G
【代码】【组合计数 or 树DP】2021 icpc 上海 G。原创 2023-09-01 00:33:02 · 200 阅读 · 0 评论 -
【暴力DP】2021 icpc上海 I
设 dp[i][j][k]表示 前 i 个物品,已经翻倍了 j 次,A点数 - B点数为 k 的最大价值和。注意数组里不能有负数,要加个偏移量 P。然后分为这6种决策分类讨论就好了。原创 2023-09-01 00:30:33 · 177 阅读 · 0 评论 -
【树DP】2021ICPC南京 H
然后考虑不存在tv = 3的结点,那么就是一次性走到底,再去遍历其他结点,此时贡献为 sum[u] + mx,其中 mx 为所有子节点中最大的 a[v]注意到,对于一个结点 u ,如果它的所有子节点中没有 tv = 3的,那么就肯定是沿着一棵子树走到底,然后去走剩下的子树。因为怎么转移和这些子节点中是否存在 tv = 3的结点有关,那么考虑先去把这些结点遍历一遍,看看是否存在,然后去转移。如果所有子节点中有 tv = 3的,那么可以先走到某个子节点,然后再走到这个 tv = 3的结点。原创 2023-08-30 21:52:15 · 144 阅读 · 0 评论 -
【状压+概率DP】CF678 E
设 dp[s][i] 表示,现在选的方案为 s ,且我是 i 的最终胜利的概率是多少。概率DP就是看当前状态从哪些状态转移过来,边权就是概率,加一下就好了。这是很经典的状压DP转移方式:选择两个1,然后转移。有两种情况,j 战胜 k 或 k 战胜 j。首先,n <= 18,应当想到状压。然后答案就是枚举一下我是哪个就好了。很明显,这里可以使用状压DP。根据这两种情况乘一下概率即可。原创 2023-08-30 18:24:59 · 144 阅读 · 0 评论 -
【三进制状态压缩】Gym Plates
对于数位7,第一个7为1表示数位7出现了2次,第2个7为1表示数位7出现了1次,两个都是1说明出现了3次。这个和一般的状态压缩不太一样,每个数位的状态有三种,意味着要用三进制的状态压缩。因此对于每个数位,两个都是1的状态直接是非法的,直接筛去即可。可以这样考虑:99887766554433221100。然后在转移的时候构造一个新的状态,按背包转移即可。首先读完题目思路肯定就是状压+背包。原创 2023-08-29 17:58:31 · 162 阅读 · 0 评论 -
【枚举倍数+容斥】CF803 F
很显然,设该 gcd 的个数为 sum,那么每个数都有选和不选,方案数就是 (1原创 2023-08-14 14:07:12 · 92 阅读 · 0 评论 -
【树状数组优化哈希DP】CF1801 C
【代码】【树状数组优化哈希DP】CF1801 C。原创 2023-08-13 21:24:54 · 325 阅读 · 0 评论 -
【DP+矩阵加速】CF691 E
有人只会暴力DP忘记矩阵快速幂怎么写了。原创 2023-08-08 22:48:07 · 169 阅读 · 0 评论 -
【简单DP】ABC312 D
当括号为")"时,我们可以需要判断 (加上后左括号需要继续大于右括号) if(j >= i - j) dp[i][j] = dp[i-1][j]为"?" 有两种情况,为"(" 按"("的情况处理,为")" 按")"的情况处理。最后需要判断字符数量,如果为奇数就为0,因为不和性质,偶数就输出dp[n][n/2];当括号为"("时,我们可以直接转移,dp[i][j] = dp[i-1][j-1]因此可以设dp[i][j]为前 i 个数,左-右个数为 j 的方案数。前i个字符中,左括号的数量必须大于等于右括号。原创 2023-08-05 20:54:37 · 154 阅读 · 0 评论 -
【子序列DP】CF1582 F1
因此设dp[j]为子序列异或和为 j 的结尾那个数的最小值。注意到ai只有500,且和子序列有关。为什么要这么设计,因为要保证递增。原创 2023-08-05 16:00:00 · 179 阅读 · 0 评论 -
【二分+滑动窗口优化DP】CF883 I
注意到分段DP的左端点 L 是在一个区间内的,那么我们就去维护这个区间,即滑动窗口优化DP。那么就相当于有了一个极差的限制,看能不能分组,每组至少m个元素。那么就是考虑分段DP,直接n^2很容易写。首先,要让最大值最小,很显然要二分。但是n原创 2023-08-02 20:48:51 · 196 阅读 · 0 评论 -
【树形DP+换根思想】2022牛客多校加赛 H
为什么要这么设计,我们发现,如果计算的结点是在子树里面的,那么lca就是u,子树的贡献直接就是sz[u]*cnt[u][0/1]首先,后缀0的个数可以转化成min(cnt2,cnt5),其中cnt2为2的因子个数,cnt5为5的因子个数。最后统计贡献的时候加上子树部分的贡献,取min(cnt2,cnt5)就好了。设dp[u][0/1]为,在除了u这棵子树中,2/5的因子个数。但是在这棵子树之外的贡献不能这么求,因此需要额外设计。这个虽然是树形DP,却用了换根的思想....原创 2023-08-02 19:33:28 · 505 阅读 · 0 评论 -
【贪心+01背包】Tower
因为交换相邻两个箱子只有对自身产生影响,所以可以贪心地考虑这两个箱子如何摆最优,而又因为本身上面的总重量不变,所以只用考虑这两个箱子的限制:一上一下的x,y,x 在上面还可放 sy−wx,y 在上可放 sx−wy,显然若 sy−wx>sx−wy 则 x 在上,否则 y 在上,移项一下得 sy+wy>sx+wx 则 x 在上,于是按 s+w 升序排序,然后每次都把箱子放在最下方即可。首先可以确定是个背包而且肯定要排序,但是根据什么排序不确定。原创 2023-08-01 23:53:03 · 252 阅读 · 0 评论 -
【换根DP】Subtree
【代码】【换根DP】Subtree。原创 2023-07-28 23:50:27 · 234 阅读 · 0 评论 -
【双指针优化DP】CF985E
但是平常写的分段DP都是n^2的,这里的可以发现单调性,因此考虑双指针转移。首先肯定需要排个序,然后分段DP。这里两个指针都代表两个段的右端点。原创 2023-07-28 10:57:08 · 149 阅读 · 0 评论 -
【DP】CF598E
【代码】【DP】CF598E。原创 2023-07-28 09:50:56 · 79 阅读 · 0 评论 -
【双指针优化DP】The 2022 Hangzhou Normal U Summer Trials H
然后就想了一个n^2的做法,枚举两个指针,第i个站点从第p个站点转移,讨论是走过来的还是骑过来的,计算贡献。但是这样的话从什么位置转移过来就不知道了,因此需要预处理从位置和花的钱数的关系。但是这样n^2肯定超时,因此我们去考虑特殊性质来枚举上一个状态。设dp[i][j]为到达第i个站点,已经花了j元钱的最小步数。特殊性质是,K很小,因此考虑去枚举这次花了l元钱到第i个站点。因为只有1e6个站点,因此可以以站点作为阶段。注意到K很小,因此可以尝试把这个当作第二维。原创 2023-07-27 19:31:59 · 247 阅读 · 0 评论 -
【DP】The 2022 ICPC Asia Regionals Online Contest (II) B Non-decreasing Array
要满足该数列不下降,N-2次询问,问操作i次之后。2.选择2~N的一个数,改变这个数为任意值。首先有个结论:改变一个数等效于删除这个数。1.选择2~N的一个数,删除这个数。原创 2023-07-27 16:44:46 · 107 阅读 · 0 评论 -
【前缀和优化DP】ABC 222D
【代码】【前缀和优化DP】ABC 222D。原创 2023-07-13 10:12:10 · 207 阅读 · 0 评论 -
【状态设计优化DP】ABC307 E
因为是个环,我们把环拆成一条链,然后加一个N+1,颜色和起点1相同,在这条链上DP。当i == N时,我们关注的是和前面那个颜色是否相同 + 和第一个元素是否相同。设dp[i][0]表示第 i 个元素,和第一个元素颜色不同的方案数。dp[i][1]表示第 i 个元素,和第一个元素颜色相同的方案数。但是这样设计既会爆时间也会爆空间,因此我们考虑重新设计状态。设dp[i][x]表示第i个元素,选的颜色为x的方案数。= N时,我们关注的只是和前面那个颜色是否相同。组合数不好考虑,我们去考虑DP。原创 2023-07-11 14:08:50 · 196 阅读 · 0 评论 -
期望DP入门
在选的过程中,如果选到了1-K号的某个没被选过的球,剩下就选K-1个,因此线性性质就体现在 剩下还要选多少球 中。因此设dp[k][m]为还剩下m个红色小球,且还需要选k个不同编号的红色小球的选择次数的期望。后者的期望贡献:dp[i]+=(1-k/n)*(dp[i-1]+1),边权为1。前者的期望贡献:dp[i]+=k/n*(dp[i-1]+1),边权为1。选没被选过且编号在1-K的,就是对次数有贡献的,否则就是没有贡献的。对期望有贡献的部分:m/n*(dp[k-1][m-1]+1)原创 2023-07-08 21:02:34 · 421 阅读 · 0 评论 -
【排序+背包求方案数】ABC216 F
它的转移条件是A数组中选的最大值>=B数组中选的数的和。DP中的限制条件除了多一维,也可以在转移的时候加条件。因为求的是子集的方案数,因此可以考虑给数组排序。但是这道题数据范围是5000,因此考虑DP。因为已经排好序了,因此选的Ai一定是最大值。首先求方案数,除了组合数就是计数DP。排完序之后做一次背包(子集用背包求)那么只需要对B数组做一次01背包即可。这个条件在转移的时候体现。原创 2023-07-06 16:15:08 · 90 阅读 · 0 评论 -
【DP+博弈】ABC195 E
【代码】【DP+博弈】ABC195 E。原创 2023-07-06 00:19:27 · 116 阅读 · 0 评论 -
【子序列+状压DP】ABC308 E MEX
但是随着每个位置的ai值不同,每个"MEX"子序列的mex贡献也是不一样的,所以我们可以考虑记录所有012排列的mex值,这个可以状压处理一下。首先,三元组很容易让我们联想到枚举中间那个元素,但是在这道题中不是这么搞的。可以注意到,题目是要我们统计所有子序列"MEX"对应的贡献。第一维可以表示前M,前ME,前MEX的状态。因此我们可以考虑子序列DP。原创 2023-07-02 17:52:29 · 268 阅读 · 0 评论 -
代码源树上背包 板子
因为u整棵树选的点数恰好为m,我们去枚举v这棵子树中选的点数,和前面遍历的这些多棵子树的选的点数,把结果存到tmp数组里,然后再用tmp数组给dp赋值。注意这里的sz数组,因为我们在遍历“物品”的时候,是不包含u这个结点的,因此sz一开始为0而不是1,等到所有物品遍历完之后,再算上u这个结点。树上背包在合并时这么多个子树中点对之间只有1的贡献,每对点对只会在它们的lca处有贡献,所以是n^2的。做法是在dfs序上做背包,如果不选,就是跳过这棵子树,选就从i+1的时间戳转移过来。这是标准的树上背包问题。原创 2023-06-19 15:14:33 · 134 阅读 · 0 评论 -
【换根DP】CF1324F
初始化就是:如果u本身是黑,那dp[u]=-1,否则dp[u]=1。设dp[u]为以u为根的子树中白-黑的最大值。事实上,S2很难求,根本不需要去求它。因此只需要把dp[v]分类讨论即可。先去树形DP求出DP值,这很好求。原创 2023-06-18 23:16:44 · 92 阅读 · 0 评论 -
【*1900 换根DP】CF1092F
然后考虑换根,可以注意到u子树部分深度加1,v子树部分深度-1,因此方程就是dp[v]=dp[u]+sum-sz[v]-sz[v]如果要直观算贡献,一般是将u子树去掉v的那部分和v子树分开来考虑变化量。如果实在想不清楚,可以手推样例:(这里是样例1)设dp[u]为在以u为根的子树上,所有点的贡献。感觉很简单,根本没有1900的难度。首先先树形DP,然后dfs换根。原创 2023-06-18 22:28:02 · 69 阅读 · 0 评论 -
【换根DP】生活在树上
是根据u结点的dp值和v的dp值更新儿子结点的dp2值,即dp2[v]=...dp[u]+....的形式。看数据范围是1e6且是统计问题,求的是对于每一个点的统计问题,那就逃不出是换根DP了。设dp[u][j]为以u为根的子树中,离根u的距离是j的结点个数。然后考虑换根,换根的时候注意是从上到下更新dp数组。首先dfs1一次把树形DP求出来,然后再考虑换根。这个很容易转移,但是注意要对边权分类讨论。原创 2023-06-18 20:50:08 · 71 阅读 · 0 评论 -
【枚举区间思想+DP】子串的子序列
这里的DP并不是传统意义的子序列DP,也就是说,并不是枚举两个指针然后转移(LIS),也不是统计前缀满足某个性质的子序列的最值(接龙数列 or 绝世好题),这里用的是状态机DP。为什么是这样设计的,其实一开始想的应该只是ac的数量的奇偶性,但是发现这样不能算贡献,考虑多一个字符c,贡献还与前缀a的数量的奇偶性有关,所以应该还有加上一维。设dp[i][0/1][0/1]表示,前i个字符,a的数量的奇偶性是0/1,ac的数量的奇偶性是0/1的。我们去枚举右端点r,然后计算满足条件的左端点的个数。原创 2023-06-18 15:28:40 · 465 阅读 · 0 评论 -
【树形DP+可重集排列】至至子的公司排队
关于计数类的树形DP,都可以把一棵子树的所有状态想象成一列,然后多棵子树进行匹配(乘法原理)先是乘法原理把所有儿子的dp值乘起来,然后注意到对于同一棵子树的拓扑序而言,顺序是确定的,那么森林的方案数怎么求呢?其实就是把这么多棵树看作子树,再求一下可重集排列即可。设dp[u]为,以u为根的子树的拓扑序的种类数,然后去考虑它的子树。其实题目问的就是,森林的拓扑序有几种。那么我们先去考虑一棵树的拓扑序有几种。这点很重要,我根本没想到这点qwq。这个可以用树形DP来解决。原创 2023-06-18 11:59:39 · 619 阅读 · 0 评论