LCT小结

LCT:

类似于树链剖分吧我是这么认为的
要学会LCT首先你要先学会Splay及其区间翻转操作

基础

  • 辅助树:
    ①Splay以深度为为关键字,维护每条链的信息(每条链一个splay
    ②其根的父亲指向这条链的链顶的父亲
    ③记住每次splay时要先从上往下下放lazy

操作

  • 判断是否是根
    Isroot(x):只要判断这个点x在splay上的根是否有它这个儿子即可(第点)

  • 把这个点在原树上到根的链变为重链
    Access(x):x到原树上每次往上跳,splay(x),断掉它的右儿子,接上上次的点即可(第点)

  • 把当前点变为原树的根
    Makeroot(x):Access(x) splay(x) 区间翻转即可(第点)

  • 找x在原树上的根
    Findroot(x):Access(x) Splay(x) 一直跳左儿子即可(第点)

  • 弄出x,y在原树上的路径(x,y连通)
    Split(x, y):Makeroot(x) Access(y) Splay(y) 此时y的左儿子为x(splay时的性质)

  • 接原树边x,y(x,y不连通)
    Link(x, y):Makeroot(x) x认y作splay中的fa即可

  • 断原树边x,y(x,y连通)
    Cut(x, y):Split(x, y) 此时y为x的父亲,直接x的父亲y的左儿子=0

一些套路

LCT可以做无排序的kruskal(problem:魔法森林)
边权:新建点变为点权
LCT可以动态维护连通性
等。。。

听说findroot不splay会被卡

我没加没被卡过(逃

最好加一下
板子

IL int Son(RG int x){
    return ch[1][fa[x]] == x;
}

IL int Isroot(RG int x){
    return ch[0][fa[x]] != x && ch[1][fa[x]] != x;
}

IL void Update(RG int x){
//维护信息
}

IL void Reverse(RG int x){
    if(!x) return;
    rev[x] ^= 1, swap(ch[0][x], ch[1][x]);
}

IL void Pushdown(RG int x){
    if(!rev[x]) return;
    rev[x] = 0, Reverse(ch[0][x]), Reverse(ch[1][x]);
}

IL void Rotate(RG int x){
    RG int y = fa[x], z = fa[y], c = Son(x);
    if(!Isroot(y)) ch[Son(y)][z] = x; fa[x] = z;
    ch[c][y] = ch[!c][x], fa[ch[c][y]] = y;
    ch[!c][x] = y, fa[y] = x, Update(y);
}

IL void Splay(RG int x){
    S[S[0] = 1] = x;
    for(RG int y = x; !Isroot(y); y = fa[y]) S[++S[0]] = fa[y];
    while(S[0]) Pushdown(S[S[0]--]);
    for(RG int y = fa[x]; !Isroot(x); Rotate(x), y = fa[x])
        if(!Isroot(y)) Son(x) ^ Son(y) ? Rotate(x) : Rotate(y);
    Update(x);
}

IL void Access(RG int x){
    for(RG int y = 0; x; y = x, x = fa[x]) Splay(x), ch[1][x] = y, Update(x);
}

IL int Findroot(RG int x){
    Splay(x); while(ch[0][x]) x = ch[0][x]; Splay(x); return x;
}

IL void Makeroot(RG int x){
    Access(x), Splay(x), Reverse(x);
}

IL void Link(RG int x, RG int y){
    Makeroot(x), fa[x] = y;
}

IL void Split(RG int x, RG int y){
    Makeroot(x), Access(y), Splay(y);
}

IL void Cut(RG int x, RG int y){
    Split(x, y), ch[0][y] = fa[x] = 0, Update(y);
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8639164.html