zoukankan      html  css  js  c++  java
  • 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,比较巧妙。

  • 相关阅读:
    我要把铁路修到威斯特摩兰
    1新建空白jasperreport模板
    oracle权限
    swagger配置
    lombok插件基本使用
    oracle与sqlserver的区别
    yaml语法学习
    第一个SpringBoot
    spring多环境切换
    JSR303数据校验
  • 原文地址:https://www.cnblogs.com/cszmc2004/p/13140564.html
Copyright © 2011-2022 走看看