LCT

【算法简介】

又是一个大数据结构!

简单的说,LCT是维护了一个森林,每个树都是一棵splay,由虚边连接着各个树

支持操作:

  • 查询、修改链上的信息(最值,总和等)
  • 随意指定原树的根(即换根)
  • 动态连边、删边
  • 动态维护连通性

性质:

每一个Splay维护的是一条从上到下按在原树中深度严格递增的路径,且中序遍历Splay得到的每个点的深度序列严格递增。

边分为实边和虚边,实边包含在Splay中,而虚边总是由一棵Splay指向另一个节点(指向该Splay中中序遍历最靠前的点在原树中的父亲)。

操作函数:

1.access

access即为打通根节点到指定节点的实链,使得一条中序遍历以根开始、以指定点结束的Splay出现。

实现方式:

  1. 转到根
  2. 换儿子
  3. 更新信息
  4. 当前操作点切换为轻边所指的父亲,转1
void access(int x)
{
    for(int y=0;x;y=x,x=fa(x))
        splay(x),rc(x)=y,pushup(x);
}

2.makeroot

makeroot旨在将指定节点转换为原树的根

void pushrev(int x)
{
    swap(lc(x),rc(x));
    tr[x].rev^=1;
}
void makeroot(int x)
{
    access(x); splay(x);
    pushrev(x);
}

3.findroot

findroot找到原树的根,一般用于判断连通性

int findroot(int x)
{
    access(x); splay(x);
    while(lc(x)) pushdown(x),x=lc(x);
    splay(x);
    return x;
}

4.split

split是把x-y的路径取出来

void split(int x,int y)
{
    makeroot(x);
    access(y); splay(y);
}

5.link

连接x-y的边

void link(int x,int y)
{
    makeroot(x);
    if(findroot(y)==x) return;//保证连边合法时不用加
    fa(x)=y;
}

6.cut

断开x-y的边

void cut(int x,int y)
{
    makeroot(x);
    if(findroot(y)!=x || tr[x].siz>2) return;//保证断边合法时不用加
    fa(y)=rs(x)=0;
    pushup(x);
}

【习题】

1.P2387 [NOI2014] 魔法森林

这个是经典的LCT操作,不断加边,直到出现环,断一条环上最劣边继续维护即可

sol

2.P4219 [BJOI2014]大融合

典型的LCT维护子树信息,注意下access和link操作时候对虚儿子信息的影响

sol

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值