• LCT(link cut tree)大法好


    新手推荐阅读:LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)题解 P3690 【【模板】Link Cut Tree (动态树)】


    Acwing算法进阶课笔记

    动态树

    虚边 实边
    Splay维护所有的实边路径
    其中序遍历就是要维护的路径(从上到下)
    1. 本质上是维护所有实边,用splay中的后继与前驱来维护原树中的父子关系
    2. 虚边:splay的根节点来维护

    Access(x):建立一条从根节点到x的实边路径

    IL void access(int x) {//打通从根节点到x的路径,x最深
        for(R y=0; x; x=fa(y=x)) {
            splay(x),rs(x)=y,pushup(x);
        }
    }

    Make_root(x):将x变成根节点

    IL void makeroot(int x) {//把x变为原树的根
        access(x),splay(x),Rev(x);
    }

    Find_root(x):找到x所在的根节点

    IL int findroot(int x) {//找到x的原树的根
        access(x),splay(x);
        while(ls(x)) pushdown(x),x=ls(x);
        return x;
    }

    Spilt(x,y):将x到y的路径变成实边路径

    IL void split(int x,int y) {//y维护x-y路径上的信息
        makeroot(x),access(y),splay(y);
    }

    Link(x,y):若x,y不连通,则加入(x,y)这条边

    IL void link(int x,int y) {
        makeroot(x);if(findroot(y)!=x)  fa(x)=y;
    }

    Cut(x,y):若x,y之间有边,则删掉该边

    IL void cut(int x,int y) {
        split(x,y);
        if(fa(x)==y&&rs(x)==0) fa(x)=ls(y)=0,pushup(y);
    }

    Isroot(x):判断x是否是所在splay的根节点

    IL int nroot(int x) //返回1说明x不是根,返回0说明x是根 
    {return ls(fa(x))==x||rs(fa(x))==x;}

    P3690 【模板】Link Cut Tree (动态树)

    萌新写代码~码风跟喻队学的

      1 #include<bits/stdc++.h>
      2 #define IL inline
      3 #define R register int
      4 #define ls(x) a[x].ch[0]
      5 #define rs(x) a[x].ch[1]
      6 #define fa(x) a[x].fa
      7 
      8 using namespace std;
      9 const int N=1e5+5,inf=0x3f3f3f3f;
     10 
     11 IL int read() {
     12     int f=1;
     13     char ch;
     14     while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
     15     int res=ch-'0';
     16     while((ch=getchar())>='0'&&ch<='9') res=res*10+ch-'0';
     17     return res*f;
     18 }
     19 
     20 int n,m;
     21 struct hh {
     22     int ch[2],fa,val,rev,sum;
     23 } a[N];
     24 
     25 IL int chk(int x) {return x==rs(fa(x));}
     26 IL void Rev(int x) {swap(ls(x),rs(x));a[x].rev^=1;}
     27 IL void pushup(int x) {a[x].sum=a[ls(x)].sum^a[rs(x)].sum^a[x].val;}
     28 IL int nroot(int x) //返回1说明x不是根,返回0说明x是根 
     29 {return ls(fa(x))==x||rs(fa(x))==x;}
     30 
     31 IL void pushdown(int x) {
     32     if(a[x].rev) {
     33         a[x].rev=0;
     34         if(ls(x)) Rev(ls(x));
     35         if(rs(x)) Rev(rs(x));
     36     }
     37 }
     38 
     39 IL void pushall(int x) {
     40     if(nroot(x)) pushall(fa(x));
     41     pushdown(x);    
     42 }
     43 
     44 IL void rotate(int x) {
     45     int y=fa(x),z=fa(y),k=chk(x),w=a[x].ch[k^1];
     46     if(nroot(y)) a[z].ch[chk(y)]=x;fa(x)=z;
     47     if(w) fa(w)=y;a[y].ch[k]=w;
     48     fa(y)=x;a[x].ch[k^1]=y;
     49     pushup(y);pushup(x);
     50 }
     51 
     52 IL void splay(int x) {//把x转到splay的根 
     53     pushall(x);
     54     while(nroot(x)) {
     55         int y=fa(x);
     56         if(nroot(y)) rotate(chk(x)^chk(y)?x:y);
     57         rotate(x);
     58     }
     59 }
     60 
     61 IL void access(int x) {//打通从根节点到x的路径,x最深
     62     for(R y=0; x; x=fa(y=x)) {
     63         splay(x),rs(x)=y,pushup(x);
     64     }
     65 }
     66 
     67 IL void makeroot(int x) {//把x变为原树的根
     68     access(x),splay(x),Rev(x);
     69 }
     70 
     71 IL int findroot(int x) {//找到x的原树的根
     72     access(x),splay(x);
     73     while(ls(x)) pushdown(x),x=ls(x);
     74     return x;
     75 }
     76 
     77 IL void split(int x,int y) {//y维护x-y路径上的信息
     78     makeroot(x),access(y),splay(y);
     79 }
     80 
     81 IL void link(int x,int y) {
     82     makeroot(x);if(findroot(y)!=x)  fa(x)=y;
     83 }
     84 
     85 IL void cut(int x,int y) {
     86     split(x,y);
     87     if(fa(x)==y&&rs(x)==0) fa(x)=ls(y)=0,pushup(y);
     88 }
     89 
     90 int main() {
     91     n=read();
     92     m=read();
     93     for(R i=1; i<=n; ++i) a[i].val=a[i].sum=read();
     94     while(m--) {
     95         int op=read(),x=read(),y=read();
     96         if(!op) split(x,y),printf("%d
    ",a[y].sum);
     97         else if(op==1) link(x,y);
     98         else if(op==2) cut(x,y);
     99         else makeroot(x),a[x].val=y,pushup(x);
    100     }
    101     return 0;
    102 }
    展开这里看完整代码
  • 相关阅读:
    事件的记忆碎片
    委托的记忆碎片
    Jquery的集合方法EACH()
    sql server中的 SET NOCOUNT ON 的含义
    nyist 299 Matrix Power Series
    poj 1061 青蛙约会
    nyist 488 素数环
    nyist 301 递推求值
    nyist 95 众数问题
    nyist 640 Geometric sum
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/14524249.html
Copyright © 2020-2023  润新知