LCT小结

来源:互联网 发布:淘宝店铺如何登陆 编辑:程序博客网 时间:2024/05/21 17:30

各种操作

1.isrt(x) 判断x是否为当前辅助树的根

    inline bool isrt(int x){        return R(F(x))!=x&&L(F(x))!=x;    }

2.pushup(x) 合并答案更新

    //举例    inline void pushup(int i){        T[i].mx=max(T[L(i)].mx,T[R(i)].mx);        T[i].mx=max(T[i].mx,T[i].v);    }

3.pushdown(x) x下传标记

注意要维护左右两个值时 修改要先pushdown一下,例如BZOJ2243

inline void pushdown(int x){        if(T[x].rev){            T[x].rev=0,T[L(x)].rev^=1,T[R(x)].rev^=1;            Swap(L(x));Swap(R(x));        }        if(T[x].mk){            int mk=T[x].mk;            if(L(x))mark(L(x),mk);            if(R(x))mark(R(x),mk);T[x].mk=0;        }    }   inline void pushdown(int x){//一般        if(T[x].rev){            T[x].rev^=1,T[L(x)].rev^=1,T[R(x)].rev^=1;            swap(L(x),R(x));        }    }

4.Pushdown(x) 将辅助树中所有祖先标记下传

    void Pushdown(int x){        if(!isrt(x))Pushdown(F(x));        pushdown(x);    }

5.splay(x) 将x旋到辅助树的根

    inline void splay(int x){        Pushdown(x);        while(!isrt(x)){            if(!isrt(F(x)))Rotate(x);            Rotate(x);        }    }

6.access(x) 打通到根节点的辅助树

    inline void access(int x){        for(int i=0;x;i=x,x=F(x))            splay(x),R(x)=i,pushup(x);    }

7.reverse(x) 换根

    inline void reverse(int x){        access(x),splay(x),T[x].rev^=1;    }

8.findrt(x) 找到x所在树的根

    inline int findrt(int x){        access(x);splay(x);        while(L(x))x=L(x);        return x;    }

9.link(x,y) 连接x,y

    inline int link(int x,int y){        if(findrt(x)==findrt(y))return -1;        reverse(x),F(x)=y;        return 0;    }

10.cut(x,y) 切断x,y连边

    inline int cut(int x,int y){        if(findrt(x)!=findrt(y)||x==y)return -1;        reverse(x),access(y),splay(y),F(L(y))=0,L(y)=0;pushup(y);        return 0;    }

因为换根之后x深度小于y深度,将y转到根后,由于x和y之前有虚边相连,所以x就在y左子树

操作大概就这些,具体题目具体分析

子树信息维护

每个节点的信息分为虚子树信息与总信息和

pushup时总信息和等于虚子树信息+实子树信息

access时将新实子树的信息从虚边信息中删去,将新虚子树的信息加进来即可,维护某些最大最小值每个节点开个muitset就好了

举例

    inline void access(int x){        for(int i=0;x;i=x,x=F(x)){            splay(x);            if(R(x))T[x].chain.insert(lmx(R(x))),T[x].path.insert(mx(R(x)));            if(i)T[x].chain.erase(T[x].chain.find(lmx(i))),T[x].path.erase(T[x].path.find(mx(i)));            R(x)=i,pushup(x);        }    }

某些经典的标记

树上最大连续子段和

    inline void pushup(int x){        sz(x)=sz(L(x))+sz(R(x))+1;        S(x)=S(L(x))+S(R(x))+T[x].val;        Ls(x)=max(Ls(L(x)),S(L(x))+T[x].val+Ls(R(x)));        Rs(x)=max(Rs(R(x)),S(R(x))+T[x].val+Rs(L(x)));        ms(x)=max(max(ms(L(x)),ms(R(x))),Rs(L(x))+T[x].val+Ls(R(x)));    }

颜色段数量

   inline void pushup(int x){        T[x].sum=T[L(x)].sum+T[R(x)].sum+1;        if(L(x))Lc(x)=Lc(L(x)),T[x].sum-=(T[x].c==Rc(L(x)));else Lc(x)=C(x);        if(R(x))Rc(x)=Rc(R(x)),T[x].sum-=(T[x].c==Lc(R(x)));else Rc(x)=C(x);    }

动态图维护

最小生成树

最小生成树具有环切性质,加入一条边时删除环上最大边即可

最小极差路径

(没有找到题…,找到了务必告诉我)
从小到大枚举最大边长,然后在这最大边长下使最小路径最大,动态最小生成树即可

二分图

维护关于删除时间的最大生成树
一个奇环的影响仅取决于环上删除时间最小的边
对于每个时刻
加入一条边时
若它为树边直接加
若形成环,则弹出删除时间最小的边,若同时为奇环,则将最小边加入集合,表示这条边存在时,图中总有奇环
(偶环不用加这条边,因为若之后加入的边与这条边形成了奇环,那么新边一定能与其他边构成奇环)
删去一条边时
若为树边直接删
若在集合中,在集合中删去
这样,在每一时刻,若集合大小为0则图为二分图

ETT+LCT 、AAA树

这坑以后再填吧…

0 0
原创粉丝点击