CEOI魔法树

CEOI里面较简单的题。

先说我的做法。

首先要注意到一个性质:如果点x是点y的父亲,则点x父亲边切割的时间t一定要大于等于点y。

原因是如果点x切割的时间小于点y切割的时间,则点x子树时间非t成熟的果子都会被丢弃。

如果我们把y的父亲切割的时间设为t,则x子树内时间不为t成熟,且不在y的子树内的果实还是能被收获。

这样子更优。

我们可以设计一个暴力dp。

设f[x][i]表示x节点的切割时间为i,g[x][i]表示x节点的切割时间<=i的最大收益。

则设son为x的儿子,f[x][i]+=max(cnt,g[son][i-1])其中cnt为son内的成熟时间为i的果实的数量。

这样子太慢了。

注意到f[x][i]如果x节点内没有i,则f[x][i]是无意义的。

所以可以使用map来维护f,g,cnt

设f[],g[],cnt[]数组。

维护cnt时对应部分直接相加。

维护f,g时直接按照定义即可。

时间复杂度nlog^2n

再说题解做法。

题解也是注意到了这条性质。但是dp和我的做法不同。

设f[x][i]表示前i天的最大收益。

当i<=d[x]时,切断父亲边不会造成影响,所以f[x][i]+=f[son][i]

当i>d[x]时,要对上面求出来的结果取max。

但是还有x节点被切断这个选项,所以设val,对于每个子树,val+=f[son][d[x]]

由于切割了当前节点会产生贡献,所以在计算dp值时要+=w[x]

最后前缀max一下得到答案。

维护f[x][]的差分表。只维护>0的位置。在更新时找到第一个>=d[x]的位置。

设v=val。

遍历这个位置,当遇到一个值时,设为p如果v>p,v-=p并且把这个值从map中删除。(现在由于当前点的值>val所以差分表内这个元素被删除)

否则在d[x]位置的差分值-=v并且跳出循环。

时间复杂度也是nlog^2n,比较巧妙。

原文地址:https://www.cnblogs.com/cszmc2004/p/13140564.html