2020 Multi-University Training Contest 7 F题
有一个N个点的树,给予其中M个操作,每次选其中一个点x,{x, r, v},给它一个影响范围为r的权值为v的值,我们现在想要选取最多的权值点,使得两两之间是没有可重叠区间的。
这个问题画在一维平面上其实很好做,也就是对于一段排序,然后维护的就是一个线段树优化dp,当我们选取这个点pos的时候,我们只能选择的点,或者说,我们假设在中,如果选择其他的更优,那么,我们可以不将这个点加进我们所选的集合中去。
于是,可以讲这个操作转换为,我们先将影响深度深的点给放进去,然后按照上面的类似贪心方法进行判断。
如果我们取这个点,比之前选取的点更优的话,我们可以选择这个点代替和它冲突的点,当然,还是可以继承和它不冲突的点的,于是,我们首先对影响区间最深的点开始这样的操作,这样的目的是为了我们其实只用考虑一个端点,而且用一个类似于差分的思想,我们可以判断取这个点是否更优。
画图说明:
如果存在这样一个点u,我们设它的深度为,然后对于u点假如存在一个影响的范围,可以知道它最向上影响的深度为的点,我们根据这个信息,来对所有的点进行降序排序,于是,可以考虑之后放入的点v,如果被之前覆盖的点能够影响到的话,也就是对应它的向上步的点(深度为,或者当为小于等于0时就是原树根节点),在点v的范围内,所以,我们将u的贡献点放在它向上r步的点,然后把它产生的贡献放在该点上。
然后,现在就是查询有多少的冲突贡献,我们可以算它覆盖范围内的点的权值和即可,当然,这里的“点”指的是原点向上r步的点。
贡献:假设冲突的点产生的总贡献为sum,那么这个点如果要取的话(如果它本身的价值还不足sum的话,要它何用?),那么它产生的贡献为。所以,对于放进去的第一个点,它的贡献就是,因为在它之前就没有任何贡献了,所以根据这样的信息,我们可以维护出来所有点的关系,又因为它是根据“向上r步”的点来进行操作的,所以保证了影响点的深度一定是上升的,所以不存在先取之前的,而跳过中间的点的这样的情况。
操作实现
现在问题转化了,变成了求它的r步范围内的“权值点”的权值之和,那样,我们可以用动态点分治来实现,因为按照类似时间戳这样的方式进行插入,所以不可永久化,我们用一个数据结构维护这个关系即可(自然选用简单的树状数组啦!)。
所以,就是一个差分的关系了,我们找到这个点,然后不断的向它的点分治父亲节点走,每次算向周围距离的点的权值和,当然,这样就很容易把自己方向的点给多算了,所以点分治的时候记录在自己方向上的father的下一个点即可。
Code
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include