Link cut tree

本文深入探讨了树链剖分与LCT(Link Cut Tree)数据结构,详细介绍了这两种数据结构的基本思想、核心操作以及它们在树上操作中的应用,如链上求和、求最值、修改等。LCT通过动态平衡树Splay实现,能够灵活地维护树的链状结构,适应各种树形变化。access和makeroot是LCT的重要操作,前者用于访问并调整树结构,后者用于将指定节点设为树的根。
摘要由CSDN通过智能技术生成


前言

维护一棵树,支持以下操作:

1.链上求和;
2.链上求最值;
3.链上修改;  
4.子树修改;
5.子树求和;
6.换根;
7.断开树上一条边;
8.连接两个点,保证连接后仍然是一棵树。


思想

树链剖分有重链和轻边。LCT也一样,分实(重)边和虚(轻)边。一个节点最多连出一条向儿子的实边,因此实边会聚集成链。根据树链剖分的思想,需要用一种数据结构来维护实边组成的链。树链剖分使用了线段树来维护,但线段树显然很静态。

我们思考可以使用能动态的平衡树——splay。

概念

Preferred Child:偏爱儿子,偏爱儿子与父亲节点同在一棵Splay中,一个节点最多只能有一个偏爱儿子(注意,LCT的偏爱儿子与树链剖分的重儿子迥乎不同,后者是点数最大的儿子,而前者则是随便的);
Preferred Edge:实边,连接父亲节点和偏爱儿子的边;
Preferred Path:偏爱路径,由实边及实边连接的节点构成的链;
Auxiliary Tree:辅助树,由一条偏爱路径上的所有节点所构成的Splay称作这条链的辅助树。每个点的键值为这个点的深度,即这棵Splay的中序遍历是这条链从链顶到链底的所有节点构成的序列。辅助树的根节点的父亲指向链顶的父亲节点,然而链顶的父亲节点的儿子并不指向辅助树的根节点。
  ps:实边连起来会组成偏爱路径,偏爱路径之间没有公共点。
  树链剖分的重链是固定的,但是LCT的偏爱路径是可以改变的。
  若一个不在偏爱路径上的点也视为一条没有实边的偏爱路径,那么偏爱路径之间是用虚边连接的。

基础操作:so、link、if_root

bool so(int x)
{
    return son[fat[x]][1]==x;
}
void link(int f,int x,bool d)
{
    son[fat[x]=f][d]=x;
}
bool if_root(int x)
{
    return !fat[x]||son[fat[x]][so(x)]!=x;
}

核心操作:access

access(x)的真正含义:让x节点不含偏爱儿子,同时x到根节点所有边均为实边。
  算法的流程如下:
  因为x节点不能含偏爱儿子,先将x旋至其所在splay的根,然后断开右子树(变为虚边)。
接着顺着偏爱路径往上爬,每遇到一条虚边,同样把虚边连向的节点y旋至y所在splay的根然后断开y的右子树(使y不含有偏爱儿子),并把x所在splay接在y的右子树(把虚边改为实边)。
  这就完成了access。

void access(int y)
{
    int x=0;
    while(y)
    {
        splay(y);
        link(y,x,1);
        x=y;
        y=fat[y];
    }
}

重要操作:makeroot

makeroot(x)即为将x变为整棵LCT的根。
  算法流程如下:对x进行access,然后观察,我们发现虚边子树会随着依附子树一起选择;而x到根的路径则会在同一棵splay里,且x是深度最大的点。

void makeroot(int x)
{
    access(x);
    splay(x);
    fan(x);
}

容易看出,makeroot操作的复杂度与access一致。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值