ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「tricks」整体DP

2021-09-29 16:06:42  阅读:194  来源: 互联网

标签:结点 min dep tricks 整体 rm 线段 DP


不太了解这个东西的具体定义是什么,总之应该是一个用数据结构维护 DP 状态的某几个维度的 trick 吧。

事实上你可以把这篇 post 理解为三个题的解集。

先直接来看 noi2020 - Destiny 这个题。

给定一棵树 T = ( V , E ) T = (V, E) T=(V,E) 和点对集合 Q ⊆ V × V \mathcal Q \subseteq V \times V Q⊆V×V ,满足对于所有 ( u , v ) ∈ Q (u, v) \in \mathcal Q (u,v)∈Q,都有 u ≠ v u \neq v u​=v,并且 u u u 是 v v v 在树 T T T 上的祖先。其中 V V V 和 E E E 分别代表树 T T T 的结点集和边集。求有多少个不同的函数 f f f : E → { 0 , 1 } E \to \{0, 1\} E→{0,1}(将每条边 e ∈ E e \in E e∈E 的 f ( e ) f(e) f(e) 值置为 0 0 0 或 1 1 1),满足对于任何 ( u , v ) ∈ Q (u, v) \in \mathcal Q (u,v)∈Q,都存在 u u u 到 v v v 路径上的一条边 e e e 使得 f ( e ) = 1 f(e) = 1 f(e)=1。由于答案可能非常大,你只需要输出结果对 998 , 244 , 353 998,244,353 998,244,353(一个素数)取模的结果。

我们略过 DP 的过程,直接给出其定义 f ( x , j ) f(x,j) f(x,j) 表示考虑子树 i i i,限制条件的 v ∈ s u b t r e e ( x ) v\in{\rm subtree}(x) v∈subtree(x) 且限制 ( u , v ) (u,v) (u,v) 尚未被满足, u u u 的深度最深且 j = d e p ( u ) j={\rm dep}(u) j=dep(u) 的不同映射 f : E s u b t r e e ( x ) → { 0 , 1 } f:E_{{\rm subtree}(x)}\rightarrow\{0,1\} f:Esubtree(x)​→{0,1} 数量,以及其转移 f ( x , i ) = f ( x , i ) ∑ y ∈ s u f ( x ) ( ∑ j = 0 d e p ( x ) f ( y , j ) + ∑ j = 0 i f ( y , j ) ) + f ( y , i ) ∑ j = 0 i − 1 f ( x , j ) f(x,i)= f(x,i)\sum\limits_{y\in{\rm suf}(x)}\left(\sum\limits_{j=0}^{{\rm dep}(x)}f(y,j)+\sum\limits_{j=0}^{i}f(y,j)\right)+f(y,i)\sum\limits_{j=0}^{i-1}f(x,j) f(x,i)=f(x,i)y∈suf(x)∑​(j=0∑dep(x)​f(y,j)+j=0∑i​f(y,j))+f(y,i)j=0∑i−1​f(x,j)。

令 g ( x ) g(x) g(x) 为 f ( i ) f(i) f(i) 的前缀和,得到平方级算法。

如果我们考虑把 DP 的第二维度状态放到线段树上,那么子树的合并就可以放到线段树上去做,即使用线段树的合并 trick 来做 DP。

我们来看看合并的具体过程。贴近实现,我们令 m e r g e : { ( x , y , l , r , s x , s y ) } → n o d e {\rm merge}:\{(x,y,l,r,s_x,s_y)\}\rightarrow{\rm node} merge:{(x,y,l,r,sx​,sy​)}→node 表示线段树合并的过程,其中 s x s_x sx​ & s y s_y sy​ 表示 DP 的前缀和(即 g g g),在实现(以及下文的讲解)中,均把这两个变量视作别名。

有这样几种情形需要探讨。

  • l = r l=r l=r:此时应该把 f ( y , l ) f(y,l) f(y,l) 合并到 f ( x , l ) f(x,l) f(x,l) 中,直接对线段树结点维护的 DP 值进行修改;
  • x = Ω x=\Omega x=Ω:此时 f ( x ) f(x) f(x) 的 DP 值并没有意义,在本题中可以视作零。于是打乘法标记即可;
  • y = Ω y=\Omega y=Ω:与上一条类似。

于是得到解决,参考实现。

再来看 pkuwc2018 - Minimax 这个题。

给出一棵有 n n n 的结点的二叉有根树,并给出其叶子结点的权值,对于一个非叶子结点,其权值有 p i p_i pi​ 概率取得儿子中的最大值, 1 − p i 1-p_i 1−pi​ 的概率取得最小值。

令 { v i } \{v_{i}\} {vi​} 表示最终根结点( 1 1 1-th 结点)的所有可能取值(升序排列),其个数记为 m m m,每一个 v i v_i vi​ 取得的概率记为 r i r_i ri​,将其按照 h a s h ( i ) = i × v i × r i {\rm hash}(i)=i\times v_i\times r_i hash(i)=i×vi​×ri​ 的规则求出 ∑ i h a s h ( i ) \sum_i{\rm hash}(i) ∑i​hash(i)。

与上一题类(完 全)似(一 致)地,同样略过 DP 的过程,给出其定义 f ( i , j ) f(i,j) f(i,j) 表示结点 i i i 取得值 j j j 的概率,以及其转移 f ( i , j ) = ∑ v ∈ s u f ( i ) f ( v , j ) ( p i ∑ 1 ⩽ k < j f ( v ′ , k ) + ( 1 − p i ) ∑ j < k f ( v ′ , k ) ) f(i,j)=\sum\limits_{v\in{\rm suf}(i)} f(v,j)\left(p_i\sum\limits_{1\leqslant k<j}f(v',k)+(1-p_i)\sum\limits_{j<k}f(v',k)\right) f(i,j)=v∈suf(i)∑​f(v,j)(pi​1⩽k<j∑​f(v′,k)+(1−pi​)j<k∑​f(v′,k)),其中 v ′ v' v′ 表示 s u f ( i ) ∖ { v } {\rm suf}(i)\setminus\{v\} suf(i)∖{v} 中的唯一取值。

令 g ( i ) g(i) g(i) 为 f ( i ) f(i) f(i) 的前缀和(显然这里的 ∞ \infty ∞ 并不是「真正的无限」),得到平方级的算法。

同样考虑把 DP 的第二维度状态放到线段树上,在线段树合并时维护 s x s_x sx​ & s y s_y sy​ 表示 DP 的前缀和,直接维护即可。

参考实现。

最后来看到 codeforces - 671D / Roads in Yusland

给定一棵 n n n 个点的以 1 1 1 为根的树。有 m m m 条路径 ( x , y ) (x,y) (x,y),保证 y y y 是 x x x 或 x x x 的祖先,每条路径有一个权值。你要在这些路径中选择若干条路径,使它们能覆盖每条边,同时权值和最小。

这题的平方 DP 都有一定难度……看了 duyi 的题解挺久才理解……不过如果做过 noi2020 - Destiny 的话应该会好很多。

称 r o u t e ( u , v ) {\rm route}(u,v) route(u,v) 中的 u u u 为起点, v v v 为终点,在 v v v 决策一个 route 是否被选择。参考 noi2020 - Destiny 的状态设计,令 f ( x , i ) f(x,i) f(x,i) 表示在 s u b t r e e ( x ) {\rm subtree}(x) subtree(x) 中选择了若干 routes,其中终点深度最深并且高于 d e p ( x ) {\rm dep}(x) dep(x) 的深度为 i i i 的最优方案。

转移即 f ( x , i ) = min ⁡ y ∈ s u f ( x ) { f ( y , i ) + ∑ z ∈ s u f ( x ) ∖ { y } g ( z ) } f(x,i)=\min\limits_{y\in{\rm suf}(x)}\{f(y,i)+\sum\limits_{z\in{\rm suf}(x)\setminus\{y\}}g(z)\} f(x,i)=y∈suf(x)min​{f(y,i)+z∈suf(x)∖{y}∑​g(z)},其中 g ( x ) = min ⁡ 1 ⩽ i < d e p ( x ) { f ( x , i ) } g(x)=\min\limits_{1\leqslant i<{\rm dep}(x)}\{f(x,i)\} g(x)=1⩽i<dep(x)min​{f(x,i)},还需要考虑每条 route 带来的额外转移,转移式显然不赘。这些 transforming formulae 也许带有一些构造成分在里面,至少我觉得不太自然……

然后考虑线段树合并优化,你需要支持区间增量 & 全局查询最小值 & 合并(与此同时区间取 min ⁡ \min min)& 单点取 min ⁡ \min min。因为 O ( ( n + m ) log ⁡ 2 n ) O((n+m)\log_2n) O((n+m)log2​n) 的空间复杂度并不能通过此题。

考虑以时间换空间,我们采用权值平衡树 & 启发式合并来解决(参考实现中给出的是 std::set)。

平衡树上每个结点维护一个 2-tuple ( i , f ( x , i ) ) (i,f(x,i)) (i,f(x,i)),以第一关键字排序。我们依次考虑如何支持上文的操作。

  • 区间增量:如果及时把 i > d e p ( x ) i>{\rm dep}(x) i>dep(x) 的元素弹出,这就变成了全局增量,直接维护即可;
  • 全局查询最小值:这个是本题最妙的地方,因为关键字的选取,平衡树无法简单地取出最小值,我们需要更多的性质。注意到 ∀ j < k , s . t . f ( x , j ) < f ( x , k ) \forall j<k,s.t.f(x,j)<f(x,k) ∀j<k,s.t.f(x,j)<f(x,k),此时的 k k k 都是无用的,可以直接删除,这得出了此题的单调性。如此全局最小值就是平衡树上最右边的结点;
  • 合并:启发式合并即可;
  • 单点取 min ⁡ \min min:相当于插入操作,直接来即可,需要注意一些不是特别细的细节(雾)。

如此时间复杂度退成了 O ( ( n + m ) log ⁡ 2 2 n ) O((n+m)\log_2^2n) O((n+m)log22​n),但是空间复杂度优化到了 O ( n + m ) O(n+m) O(n+m),可以通过此题。

参考实现。

标签:结点,min,dep,tricks,整体,rm,线段,DP
来源: https://blog.csdn.net/weixin_42425080/article/details/120550468

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有