\(\text{Solution}\)

设 \(f_{x,i}\) 表示以 \(x\) 为根的子树 \(i\) 天后的最大收益

那么 \(f_{x,i} = \max(f_{x,i-1},w_x [d[x] \ge i] + \sum f_{v,i})\)

这样的转移时 \(O(nk)\) 的,只能拿到 \(34pts\)

再加上其他的部分分也只有 \(48pts\)

正解是在这个 \(dp\) 上优化

我们发现很多状态都是没用的

观察到 \(x\) 各个状态的值由 \(v\) 对应的状态合并上来

那么就可以考虑线段树合并

开 \(n\) 棵线段树代替 \(f\) 的第二维,也就是时间这一维

转移就成线段树的合并操作了

但发现 \(f\) 的值是前缀最大值,需要我们获得前缀最大值之后再合并(相加)才对

那么线段树合并的时候维护两棵线段树前缀最大值,给对方

合并完子树后考虑加入当前节点的贡献

\(x\) 会对它的线段树 \(d_x\) 以后的值产生影响

并且此时还需取出 \(d_x\) 前的最大值加上 \(w_x\) 才是正确的贡献

对 \(d_x\) 以后的值取 \(max\) 即可

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define re register
using namespace std;
typedef long long LL; const int N = 1e5 + 5;
int n, m, k, fa[N], tot, h[N];
struct node{int d, w;}a[N];
struct edge{int to, nxt;}e[N];
inline void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;} inline void read(int &x)
{
x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
} int size, ls[N << 5], rs[N << 5], rt[N];
LL val[N << 5], tag[N << 5]; inline void pushdown(int p)
{
if (!tag[p]) return;
if (ls[p]) val[ls[p]] += tag[p], tag[ls[p]] += tag[p];
if (rs[p]) val[rs[p]] += tag[p], tag[rs[p]] += tag[p];
tag[p] = 0;
} void update(int &p, int l, int r, int x, LL v)
{
if (!p) p = ++size, ls[p] = rs[p] = val[p] = tag[p] = 0;
val[p] = max(val[p], v);
if (l == r) return;
pushdown(p);
int mid = (l + r) >> 1;
if (x <= mid) update(ls[p], l, mid, x, v);
else update(rs[p], mid + 1, r, x, v);
} LL query(int p, int l, int r, int x)
{
if (!p || r <= x) return val[p];
pushdown(p);
int mid = (l + r) >> 1; LL res = query(ls[p], l, mid, x);
if (x > mid) res = max(res, query(rs[p], mid + 1, r, x));
return res;
} int merge(int x, int y, LL tagx, LL tagy, int l, int r)
{
if (!x && !y) return 0;
if (!y){val[x] += tagx, tag[x] += tagx; return x;}
if (!x){val[y] += tagy, tag[y] += tagy; return y;}
if (l == r)
{
tagx = max(tagx, val[y]), tagy = max(tagy, val[x]);
val[x] = max(val[x] + tagx, val[y] + tagy);
return x;
}
pushdown(x), pushdown(y);
int mid = (l + r) >> 1;
LL valx = val[ls[x]], valy = val[ls[y]];
ls[x] = merge(ls[x], ls[y], tagx, tagy, l, mid);
rs[x] = merge(rs[x], rs[y], max(tagx, valy), max(tagy, valx), mid + 1, r);
val[x] = max(val[ls[x]], val[rs[x]]);
return x;
} void dfs(int x)
{
for(re int i = h[x]; i; i = e[i].nxt)
dfs(e[i].to), rt[x] = merge(rt[x], rt[e[i].to], 0, 0, 1, k);
if (a[x].d) update(rt[x], 1, k, a[x].d, query(rt[x], 1, k, a[x].d) + a[x].w);
} int main()
{
read(n), read(m), read(k);
for(re int i = 2; i <= n; i++) read(fa[i]), add(fa[i], i);
for(re int i = 1, v; i <= m; i++) read(v), read(a[v].d), read(a[v].w);
dfs(1), printf("%lld\n", val[rt[1]]);
}

「CEOI2019」魔法树的更多相关文章

  1. liberOJ #2033. 「SDOI2016」生成魔咒 后缀数组

    #2033. 「SDOI2016」生成魔咒     题目描述 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1 11.2 22 拼凑起来形成一个魔咒串 [1,2] [1, 2] ...

  2. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  3. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  4. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  5. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  6. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  7. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  8. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  9. 「2014-3-17」C pointer again …

    记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

  10. 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance

    提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...

随机推荐

  1. c3 linearization详解

    MRO MRO 全称方法解析顺序(Method Resolution Order),在多重继承和多继承存在的时候,寻找属性及方法的顺序. 深度优先(DFS)与广度优先(BFS) python2 所用的 ...

  2. Django测试脚本-单表操作(增删改查)-必知必会13条-神奇的双下划线

    目录 一:Django测试脚本 1.测试环境准备 2.tests.py 3.models.py 4.切换MySQL数据库 二:单表操作 1.pk关键字与get关键字 2.增 3.删 4.修 三:必知必 ...

  3. MongoDB 索引类型介绍

    转载请注明出处: 目录 1.单字段索引 2.复合索引 3.多key索引 4.其他类型索引 5.索引额外属性 6.MongoDB 索引相关的常用sql命令 MongoDB 支持多种类型的索引,包括单字段 ...

  4. 【机器学习】李宏毅——AE自编码器(Auto-encoder)

    1.What 在自编码器中,有两个神经网络,分别为Encoder和Decoder,其任务分别是: Encoder:将读入的原始数据(图像.文字等)转换为一个向量 Decoder:将上述的向量还原成原始 ...

  5. Python全栈工程师之从网页搭建入门到Flask全栈项目实战(7) - 在线问答系统

    1.项目源码/业务逻辑 百度网盘链接:链接:https://pan.baidu.com/s/13VNfrSJE6vcL3HP1J5T8ew 提取码:00s0,项目业务逻辑自行阅读 2.项目搭建 点击新 ...

  6. 一篇文章带你了解设计模式原理——UML图和软件设计原则

    一篇文章带你了解设计模式原理--UML图和软件设计原则 我们在学习过程中可能并不会关心设计模式,但一旦牵扯到项目和面试,设计模式就成了我们的短板 这篇文章并不会讲到二十三种设计模式,但是会讲解设计模式 ...

  7. 来自一位十年.net研发老人的吐血整理:.Net技术栈-网址导航

    业余时间为什么整理这个? 内容聚合:不用一个一个搜索,我们很快可以进入常用技术官网 提高效率:多看官方文档可以最快,最准确的掌握相关的技术资讯,不用被一些没理解透或者有偏差的技术分享所带偏. 很多有经 ...

  8. Spark详解(09) - Spark调优

    Spark详解(09) - Spark调优 Spark 性能调优 常规性能调优 常规性能调优一:最优资源配置 Spark性能调优的第一步,就是为任务分配更多的资源,在一定范围内,增加资源的分配与性能的 ...

  9. Hive详解(04) - hive函数的使用

    Hive详解(04) - hive函数的使用 系统内置函数 查看系统自带的函数 hive> show functions; 显示自带的函数的用法 hive> desc function u ...

  10. 行为型模式 - 备忘录模式Memento

    学习而来,代码是自己敲的.也有些自己的理解在里边,有问题希望大家指出. 模式的定义与特点 在备忘录模式(Memento Pattern)下,为的是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该 ...