平衡树板子
题目要求维护很多条链,不难想到用平衡树,个人用的是 fhq treap 。
将边化成点,每一棵 treap 都以点边点的顺序存了一条链,代表边的点权值为边权,代表点的点权值为 $0$ 。
操作一
加边操作,合法的条件是:
-
不在同一棵子树。
-
两个点都在链头或链尾,即中序遍历最大或最小。
如果 $x,y$ 同时在链头或同时在链尾还要翻转一下 treap 。
然后把 $x$ 放最后, $y$ 放最前,两棵树之间插入边权为 $z$ 的一个代表边的点,合起来就行。
操作二
删边操作,合法的条件是:
-
在同一棵子树
-
两个点之间只隔了一个代表边的点。
满足条件就直接把那个代表边的点拆掉就行。
操作三
本质上与上面两个一样,读者自行理解。
操作四
判断一下根是否相等就好。
操作五
首先还是判断 $x,y$ 是否同根,不同根直接返回。
然后比较一下 $x,y$ 在 treap 中排名的大小,不妨设为 $rx,ry$ 。
-
如果 $rx<ry$ ,要往右边走,于是终点就是最右端的点,时间为 $x$ 节点后的边权和。
-
如果 $rx>ry$ ,要往左边走,于是终点就是最左端的点,时间为 $x$ 节点前的边权和。
实现细节
有几个坑点提一下:
-
查询根和排名需要维护节点父亲,然后从当前节点往上跳统计答案。
-
查询排名时一定要释放从根到它的所有翻转标记。
代码
1 | #include<cstdio> |

