BZOJ3786: 星系探索 Splay+DFS序

题目大意:给你一个树,支持三种操作,子树加,点到根的路径和,改变某一个点的父亲。

分析:

看起来像一个大LCT,但是很显然,LCT做子树加我不太会啊...

那么,考虑更换一个点的父亲这个操作很有意思,也就是说明,整个树的结构不会有什么大的变化,只是某个节点的父亲变了,那么也就是相当于在DFS序上顺序的变化,那么我们就可以考虑化简它的树结构,从而在序列上解决。

而对于这道题,DFS序能解决,但需要维护更多信息,而且乘法的次数多了很多次,没试,但是应该过不去。我们可以换一种序列,也就是入栈出栈序,这样就可以完美解决了。

我们动态的维护四个信息,Splay Tree该节点的子树大小,该节点的子树和,和子树正号数量-符号数量符号,Lazy标记。之后每次PushDown的时候用Lazy*num来更新sum。其他的照常。

关键是每次查询的时候,因为我们不论怎么改变这个序列,有一点从来没有变,就是对应的树上节点在Splay Tree上的节点标号,那么每次只需要找到前驱后继即可,而找到前驱后继显然最好还是用Query_rank和Query_x分别表示找到对应节点的排名和对应排名的节点编号,非递归,记得在Query_x的时候PushDown就可以了!

之后Rank1什么的,就不用在意了...毕竟Splay的常数...大家知道就好...

不过我已经尽力了...最快优化到33s,不知道还有没有其他优化...

附上代码:

  

 

posted @   Winniechen  阅读(335)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示