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


    终于把模板写了(QwQ)


    思路:(LCT)

    提交:(1)次(当然看了题解)

    题解:大佬的

    自己再记录一下:
    (fa[x])对于每颗(Splay)中的根节点,记录的是(Splay)中在真实树中最浅的点的虚边,而其他点记录的是在(Splay)中的(father)
    注意(isroot)这个操作,如果是(root)不能瞎(rot),因为此时的(fa[x])并不是在(Splay)中的(father),而是那条虚边。
    然后就是注意(cut)中的三个条件,缺一不可。

    #include<cstdio>
    #include<iostream>
    #define R register int
    using namespace std;
    namespace Luitaryi {
    namespace Fread {
    static char B[1<<15],*S=B,*T=B;
    inline char getchar() {return (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?EOF:*S++);}
    template<class I> inline I g(I& x) { x=0;
      register I f=1; register char ch; while(!isdigit(ch=getchar())) f=ch=='='?-1:f;
      do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
    }
    }using Fread::g; const int N=3e5+10;
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
    int n,m,fa[N],ch[N][2],sum[N],stk[N],vl[N]; bool tg[N];
    inline bool isroot(int x) {return ls(fa[x])!=x&&rs(fa[x])!=x;}
    inline void upd(int x) {sum[x]=sum[ls(x)]^vl[x]^sum[rs(x)];}
    inline void down(int x) {swap(ls(x),rs(x)),tg[x]^=1;}
    inline void spread(int x) {if(!tg[x]) return ; if(ls(x)) down(ls(x)); if(rs(x)) down(rs(x)); tg[x]=0;}
    inline void rot(int x) {
      R y=fa[x],d=ch[y][1]==x;
      if(!isroot(y)) ch[fa[y]][ch[fa[y]][1]==y]=x;
      fa[x]=fa[y]; fa[ch[y][d]=ch[x][d^1]]=y;
      fa[ch[x][d^1]=y]=x; upd(y);
    }
    inline void Splay(int x) {
      R y=x,top=0; stk[++top]=y;
      while(!isroot(y)) stk[++top]=y=fa[y];
      while(top) spread(stk[top]),--top;
      while(!isroot(x)) { y=fa[x];
        if(!isroot(y)) rot((ch[fa[y]][1]==y)==(ch[y][1]==x)?y:x); rot(x); 
      } upd(x);
    }
    inline void acc(int x) {for(R y=0;x;x=fa[y=x]) Splay(x),rs(x)=y,upd(x);}
    inline void mrt(int x) {acc(x),Splay(x),down(x);} //子树中所有的深度都倒转
    inline int frt(int x) {acc(x),Splay(x); while(ls(x)) spread(x),x=ls(x); Splay(x); return x;}//Splay(x)保证复杂度
    inline void split(int x,int y) {mrt(x),acc(y),Splay(x);}
    inline void link(int x,int y) {mrt(x); if(frt(y)!=x) fa[x]=y;}//y是x的father
    inline void cut(int x,int y) {mrt(x); if(frt(y)==x&&fa[y]==x&&!ls(y)) fa[y]=rs(x)=0,upd(x);} 
    inline void main() {
      g(n),g(m); for(R i=1;i<=n;++i) g(vl[i]);
      while(m--) { R op,x,y; g(op),g(x),g(y);
        if(op==0) split(x,y),printf("%d
    ",sum[x]);
        if(op==1) link(x,y); if(op==2) cut(x,y); 
        if(op==3) Splay(x),vl[x]=y;
      }
    } 
    } signed main() {Luitaryi::main(); return 0;}
    

    2019.08.06
    94

  • 相关阅读:
    kotlin的三目运算
    oracle存储过程相关整理
    LInux系统部署Java项目
    Idea集成vue
    java执行查询存储过程
    访问分享文件路径方法
    java计算程序运行时间
    IntelliJ IDEA 最新版 2019.1 安装与激活
    oracel中将子表中一个字段多条数据合并到主表的sql
    oracel根据条件不同,统计数据sql
  • 原文地址:https://www.cnblogs.com/Jackpei/p/11312167.html
Copyright © 2020-2023  润新知