【2019正睿金华集训】0802总结(树上DP)

今日学习: DP && 树上数据结构

DP:

基本DP我便不再累述,安利一下我的博客
这里我就是想讲一下老师上课讲的一些稀奇古怪 毒瘤DP题。(这里先讲一下我已经理解了的)

例1树上互质最长链;给出⼀棵n个节点的树,每个节点上有点权a_i。求最⻓的树上路径,满⾜条件:路径上经过节点(包括两个端点)点权的gcd和不等于1

每一个点权<=2*105,考虑将每一个点都分解质因数。
对于每一个节点u,设dp[u,p]表示从u点向下挂出的点权都能被p整除的最长链长度。
枚举父亲和儿子的质因数,有相同的便可以进行转移,中途累计答案即可。

例2:给出一个n个节点的树,对于1~n中的每个数k,求出最多能选出多少条互不相交的路径(边,点都不交)且路径长度为k?

考虑如果k是固定该怎么求?
考虑贪心:每一次我们枚举最高点在u的链的放置方案,这样链的两端一定插在不同的儿子中。我们发现每一个儿子对父亲的贡献只有向下到达的最深点,因为任意两条链不能重叠。那么每一次找寻儿子中最深的两个,如果大于k那么就放置,否则更新当前u的最深处。

现在得出单个k的做法,如果令f[k]表示k时的答案,发现由于n的限制,答案最多是 n k n\over{k} kn,考虑这个整除,f[k]的取值最多有 s q r t ( n ) sqrt(n) sqrt(n)取法,并且发现f[k]是单调不升的,那么只要确定一个权值相同的区间的左端点f[]的值,便可以二分出右端点的位置。然后再用以上贪心方法求出下一个区间左端点的f[]的值,以此类推…

时间复杂度为O ( n l o g n s q r t ( n ) ) (nlognsqrt(n)) (nlognsqrt(n)

例3:Easy Problems;长为n的字符串,要求删除一些字符是的子序列中不包含"hard",已知每个位置删除的代价ai,求出最小代价。

滚动数组:用f[1~4],f[1]表示目前为止没有h的最小代价,f[2]表示目前为止没有ha的最小代价,f[3]表示目前为止没有har的最小代价,f[4]表示目前为止没有hard的最小代价;

for(int i=1;i<=n;i++)//当前的位置
    {
      if(a[i]=='h') f[1]+=b[i];//到目前为止使没有h的最小价值
      if(a[i]=='a') f[2]=min(f[1],f[2]+b[i]);//到目前为止使没有ha的最小价值,为了使ha不连接,要么使h全消失,要么使a全消失 
      if(a[i]=='r') f[3]=min(f[2],f[3]+b[i]);//同理到目前为止使没有har的最小价值,前面已经得出使ha不连接的最小值,再和使r全消失的代价进行比较 
      if(a[i]=='d') f[4]=min(f[3],f[4]+b[i]);//到目前为止使没有hard的最小价值,前面得出使har无法连接的最小值,与使d全消失的代价比较即可,这样得出使没有hard一定是代价最小的 
    },最后输出f[4]就是到n位置使没有hard的最小代价了

例4:给出⼀个字符串S,这个字符串只由’A’, ’C’, ‘G’, ‘T’四个字⺟组成。
对于每个1~|S|中的每⼀个i,求出满⾜以下条件的字符串T的个数:
1.⻓度为m。
2.只由’A’, ‘C’, ‘G’, ‘T’四个字⺟组成。
3.LCS(S,T) = i.
答案对10^9+7 取模后输出。

数据范围
|S| <= 15, m <= 1000.

经典的DP套DP(毒瘤
考虑传统的求LCS,设f[i][j]表示考虑A串的前i位,考虑B串的前j位的LCS长
有如下:
1. a [ i ] ! = b [ j ] a[i]!=b[j] a[i]!=b[j] f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] ) f[i][j]=max(f[i-1][j],f[i][j-1]) f[i][j]=max(f[i1][j],f[i][j1])
2. a [ i ] = b [ j ] a[i]=b[j] a[i]=b[j] f [ i ] [ j ] = m a x f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] , f [ i − 1 ] [ j − 1 ] + 1 f[i][j]=max{f[i-1][j],f[i][j-1],f[i-1][j-1]+1} f[i][j]=maxf[i1][j],f[i][j1],f[i1][j1]+1
明显有 f [ i ] [ j − 1 ] < = f [ i ] [ j ] < = f [ i ] [ j − 1 ] + 1 f[i][j-1]<=f[i][j]<=f[i][j-1]+1 f[i][j1]<=f[i][j]<=f[i][j1]+1
因此可以将差分序列压起来,在本题中,令序列a=T,序列b=S,那么对于⼀个确定的T的前缀,当前的LCS状态可以⽤⼀个15位的⼆进制数来表示。
转移时枚举T新添的字⺟是什么,并使⽤上⾯传统的LCS计算⽅法来求出新的状态即可,累计方案.


感觉DP真的是博大精深,还有DP套DP这样的操作,震惊。
DP的精髓在于状态的设置以及转移方程,再加上一些优化。

树上数据结构

常见的树上数据结构:

1.树链剖分 2.线段树 3.主席树

常用算法:倍增思想,点分治,树上路径交

对于以上,我目前只会敲一些经典的板子。

一.支持修改边权和询问路径边权最大值:可用树剖+线段树
二.路径上第 k 大点/边权:可用主席树的前缀和性质 (目前还不会利用树剖去做)
三.距离不超过 k 的路径条数以及距离等于k的路径是否存在:点分治

树上路径交:

两条树上的路径[a,b]和[c,d]有交,则有lca(a,b)在[c,d]上或lca(c,d)在[a,b]上。
其实只要深度大的lca在另一条链上就好了,所以设x=lca(a,b)深度较大。
充分性证明:x在[c,d]上,则[a,b]和[c,d]显然有交。
必要性证明:x不在[c,d]上,如果[a,b]上有点y与[c,d]有交,因为lca(c,d)深度较小,所以y的深度必定小于x,那么x就不是lca(a,b)了,矛盾,所以如果x不在[c,d]上,[a,b]与[c,d]无交。
判断x在[c,d]上只需要判断x是lca(c,d)的儿子且x是c或d的父亲。

树上问题的拓展千奇百怪,还会有许多的算法,数据结构联系在一起,需要问题的转化,目前还不太会(坑)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值