专栏文章

当 BIT 遇到 DFS 序

算法·理论参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mir42onk
此快照首次捕获于
2025/12/04 15:25
3 个月前
此快照最后确认于
2025/12/04 15:25
3 个月前
查看原文
众所周知,当一棵树求出 DFS 序后,可以将子树拍成区间。这时,BIT 就能处理很多树上问题。
  1. 单点加,子树求和
    • 其实就是单点加,区间求和。
  2. 单点加,链求和
    • 维护每个点到根的和,那么单点加相当于子树加。
    • 链求和拆成到根的链(下同),那么链求和相当于单点查。
  3. 子树加,单点查
    • 其实就是区间加,单点查。差分即可。
  4. 链加,单点查
    • 做树上差分后,问题转化为单点加,子树求和
  5. 子树加,子树求和
    • 相当于区间加区间求和。这是一个 BIT 经典问题。
    • 还是做差分,设原数组为 aa,差分数组为 dd,前缀和数组为 sumsum
    • di=aiai1d_i=a_i-a_{i-1}ai=j=1idja_i=\sum\limits_{j=1}^id_j
    • sumi=k=1iak=k=1ij=1kdj=k=1idk×(nk+1)=(n+1)k=1idkk=1ik×dksum_i=\sum\limits_{k=1}^ia_k=\sum\limits_{k=1}^i\sum\limits_{j=1}^kd_j=\sum\limits_{k=1}^id_k\times(n-k+1)=(n+1)\sum\limits_{k=1}^id_k-\sum\limits_{k=1}^ik\times d_k
    • 我们可以维护 did_ii×dii\times d_i,进而维护前缀和。
  6. 链加,子树求和
    • 维护每个点的子树和,链加拆成到根的链。
    • 对于一次链加,只有链上的点会受影响。
    • 假设对从 uu 到根的链加 xxvv 是其中一个受影响的点,那么 vv 的子树和增加了 x×(dep[v]dep[u]+1)=x×dep[v]x×(dep[u]1)x\times(dep[v]-dep[u]+1)=x\times dep[v]-x\times(dep[u]-1)
    • 那么一个点的子树和就能表示为 au×x+bua_u\times x+b_u,分别维护 a,ba,b 即可。
    • 问题转化为链加,单点查。
  7. 子树加,链求和
    • 维护每个点到根的和,接下来考虑如何处理子树加。
    • 对于一次子树加,只有子树里的点假设对 uu 进行子树加 xxvv 是其中一个受影响的点,那么 vv 到根的和增加了 x×(depudepv+1)=x×(dep[u]+1)x×depvx\times(dep_u-dep_v+1)=x\times(dep[u]+1)-x\times dep_v
    • 那么一个点到根的和就能表示为 au×x+bua_u\times x+b_u,分别维护 a,ba,b 即可。
    • 问题转化为子树加,单点查。
  8. 链加,链求和
    • 还是维护把每个点到根的和,链加拆成到根的链。
    • 对于一次链加,整棵树都会受影响。影响分成两类。
    • 假设对从 uu 到根的链加 xxvv 是其中一个受影响的点。
      1. vvuu 的子孙。那么 vv 到根的和增加了 x×depux\times dep_u
      2. vvuu 的祖先。那么 vv 到根的和增加了 x×depvx\times dep_v
      3. 互不为祖先关系。我不会。
    • 所以还是老老实实的写树剖吧。
  9. 与树剖做法的比较
    • 时间复杂度:链加、链求和问题更优。(少一个 log\log
    • 码量:优。
    • 思维难度:劣。
    • 在时间复杂度允许且懒得思考的情况下还是写树剖吧。
Edited by r09er_yrj on 11.1711.17

评论

0 条评论,欢迎与作者交流。

正在加载评论...