点分治的重心连接形成的树就叫点分树。
对于每棵点分树我们用数据结构维护信息,这就是动态点分治。
我们修改、查询都只影响点分树从根到当前重心的一条链,由于点分树树高不超过 (log n) ,所以我们暴力往上跳复杂度有保证。
一般的套路是,我们用数据结构维护每棵点分树内节点到当前根的信息和到根的父亲的信息(避免重复统计,这也是点分治的套路)。
动态点分治一般比较套路化,代码量一般较大但不难写。
例1 震波 (BZOJ3730)
给定一棵树,在线支持两种操作:1. 查询与某点距离不超过 (k) 的点的权值和; 2. 修改某点权值。
Sol:动态点分治模板题。每棵点分树内用线段树维护子节点到当前根的距离和到根的父亲的距离。查询&修改直接按套路就可以了。
例2 【ZJOI2007】 捉迷藏
给定一棵树,每个点为黑点或白点。每次修在线改一个点的颜色或询问最远白点间距离。
Sol:同样,对于每棵点分树用可删堆维护每个子节点到当前根的距离和到根的父亲的距离,那么对于一棵点分树的答案即为所有子树到根的父亲距离的最大值和次大值之和,总答案也用可删堆维护。
例3 【HNOI2015】 开店
给定一棵树,每个点有一个颜色。每次在线询问颜色区间在 ([l,r]) 区间内所有点到某点距离之和。
Sol:不考虑颜色即为例1的简化版。考虑颜色就将每棵点分树内子节点按颜色排序,查询时直接二分区间即可。
例4 【ZJOI2015】幻想乡的战略游戏
给定一棵树,每次修改点权 (val[i]) 或询问 (displaystyle min_{u=1}^n sum_{v=1}^ndist(u,v)cdot val[v]) .
Sol:找到 (u) 即为例1的简化版。问题主要在怎么找 (u) ,即一棵树的带权重心。
我们发现,带权重心一定是从根到带权重心的一条重链。用线段树维护树链剖分,查询时二分即可。