树上莫队算法

继续回来写博客……记录点有意思的题目什么的。

貌似写过这个的没多少人……所以我也记录一点。

首先序列上的莫队大家都应该很熟悉了……

那么树上的莫队要怎么搞呢?

先来看个题目……SPOJ COT2:求树上两点间路径上有多少个不同的点权。

序列上的莫队是把询问按照左端点分块了……可是树上没有左端点,怎么办呢?我们把树分块。

按照DFS时间戳顺序,将树分成O(sqrt(n))个大小为O(sqrt(n))的块,那么树上的莫队询问排序的第一关键字就是第一个节点所在的块了!

这样分块以后,任意两个块之间的距离也是O(sqrt(n))级别的,所以时间复杂度是有保证的。

第二个关键字自然就是节点的DFS时间戳了!

但是,还有一个问题。树上的区间要怎么转移呢?要怎么从一个区间变到另一个区间呢?

这就有些难了,因为树上有LCA,貌似不好处理。

Orz了wyfcyx后,找到了vfk的博客看了一下。



用S(v, u)代表 v到u的路径上的结点的集合。
用root来代表根结点,用lca(v, u)来代表v、u的最近公共祖先。
那么
S(v, u) = S(root, v) xor S(root, u) xor lca(v, u)
其中xor是集合的对称差。
简单来说就是 节点出现两次消掉。
lca很讨厌,于是再定义
T(v, u) = S(root, v) xor S(root, u)
观察将curV移动到targetV前后T(curV, curU)变化:
T(curV, curU) = S(root, curV) xor S(root, curU)
T(targetV, curU) = S(root, targetV) xor S(root, curU)
取对称差:
T(curV, curU) xor  T(targetV, curU) = (S(root, curV) xor S(root, curU)) xor ( S(root, targetV) xor S(root, curU))
由于对称差的交换律、结合律:
T(curV, curU) xor  T(targetV, curU) = S(root, curV) xor S(root, targetV)
两边同时xor  T(curV, curU):
T(targetV, curU) T(curV, curU) xor  S(root, curV) xor 
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值