[BZOJ3730]震波

题目

  点这里看题目。
   BZOJ 目测…是炸了。

分析

  动态点分治入门题。
  首先理解什么叫 " 动态点分治 "。
  一般点分治需要离线解决,不带修改。动态点分治可以用点分治的方法在线解决问题,支持修改。
  在点分治的过程中,每个点都会成为一次分治中心进行计算。如果我们将点按照计算顺序连成一棵树的话,我们就会得到原树的一颗 " 虚树 " , 我们称之为点分树。煮个栗子:
image.png
  可以发现,由于重心的先天性质,点分树的树高为 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)
  对于本题,由于只会有单点修改(例如修改 u u u),所以我们可以在点分树上从 u u u开始,对于 u u u到点分树的根的路径进行暴力修改,这样只会有 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)个点。再深的点不会受到影响(因为对于更深的点,它们进行点分治的时候, u u u已经没有了)。
  如何维护信息?我们对于点分树上每一个点 u u u维护两个树状数组,第一个树状数组维护下标为到 u u u距离的权值和,用于直接计算贡献;第二个树状数组维护下标为到 u u u点分树上父亲距离的权值和,用于容斥扣除重复贡献。统计的方式类似于修改,我们在点分树上从 u u u开始上跳,用树状数组计算贡献。再煮个栗子:
dfsrc
  现在想必各位都懂了。
  需要注意的几点:
  1. 注意点分树上,祖先到自己的距离并不是单调递增的。因此不能中途 break。
  2. 由于我们只需要知道点分树上祖先到自己的距离和祖先的标号,且点分树深度有限,因此我们把这两个值用数组存下来即可。
  3. 树状数组需要用 vector 存。仅存下需要的空间会优化到 O ( n log ⁡ 2 n ) O(n\log_2n) O(nlog2n)(跟点分治基础时间复杂度一样),而不优化会变成 O ( n 2 ) O(n^2) O(n2), MLE。
  4. 树状数组注意下标不要变成非正数。
  5. 函数千万千万不要传 vector 的值!!!亲测会慢 10 倍!!!

代码

#include <map>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;

const int MAXN = 1e5 + 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值