题意: 一棵树,四个操作:
1、删边 + 加边
2、加入点对(x, y)
3、删除第x个加入的点对
4、询问当前所有点对之间的路径是否均经过边(x, y)
这道题是动态树维护虚边信息的好题。
考察操作4,所有点对路径均经过边(x, y),就代表着将x作为树根后,所有点对均有且只有一个点在y的子树中。(包括y)
我们将每一条路径随机一个很大的权值,并异或到对应点对的两个点上。则x作为根并access(y)后,y的实子树中只有点x。那么所有路径有且只有一个点在y子树中->y及其虚子树异或和=所有路径异或和。当然以上成立的条件是随机出的权值没有重复,异或和也不能有重复的。在int范围内随机就可以避免这个问题了。
维护一个所有路径异或和now和每个节点的信息,加入与删除路径点对时记得在总异或和与路径两端点权值中加上(清掉)该路径权值,异或一下就好。
这道题需要维护子树和,由于是第一次练习,为了写得更模板化,我多使用了几个变量:
val —> 节点权值
sum_chain —> 节点实子树权值和(包括节点本身)
val_tree —> 节点虚子树权值和(不包括节点本身)
sum_tree —> 节点及其实子树所有节点的虚子树权值和(不包括实子树节点及本身)
以上所有权值和在本题中均指异或和。
前两项是平时维护的东西,后面多出来的两项是额外维护的东西。
这些东西可以干很多事情,比如: sum_tree + sum_chain = 该节点为根的子树的和
又比如,将加法换成异或,则val ^ val_tree 就是我们要找的节点及虚子树的异或和。
在题目中,有些东西可以合在一起维护,具体问题具体分析。
维护虚边信息的动态树在写法上面有改变,尤其是node中的access操作。要留心。
|
|