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,比较巧妙。