• 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);
    }
    
  • 相关阅读:
    [LeetCode] Course Schedule
    [Algorithms] Topological Sort
    [Algorithms] Graph Traversal (BFS and DFS)
    [LeetCode] One Edit Distance
    [LeetCode] Summary Ranges
    [LeetCode] Missing Ranges
    [LeetCode] Fraction to Recurring Decimal
    17.Docker之使用dockerfile创建jdk镜像
    16.Docker之使用dockerfile创建nginx镜像
    7.Docker之dockerfile指令简介
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8639164.html
Copyright © 2020-2023  润新知