zoukankan      html  css  js  c++  java
  • 【学习笔记】LCT link cut tree

    大概就是供自己复习的吧

    1、 细节讲解

    安利两篇blog:


    2、模板

    把 $ rev $ 和 $ pushdown $ 的位置记清

    #define lc son[x][0]
    #define rc son[x][1]
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=300009;
    int son[maxn][2] ,fa[maxn], st[maxn];
    int lazy[maxn], s[maxn], v[maxn];
    bool ws(int x){
        return son[fa[x]][1]==x;
    }
    bool isroot(int x){
        return !(son[fa[x]][0]==x||son[fa[x]][1]==x);    
    }
    void update(int x){
        s[x]=s[lc]^s[rc]^v[x];
    }
    void rev(int x){
        swap(lc,rc); lazy[x]^=1;
    }
    void pushdown(int x){
        if(lazy[x]){
            if(lc) rev(lc);
            if(rc) rev(rc);
            lazy[x]=0;
        }
    }
    void rot(int x){
        int f=fa[x], ff=fa[f], w1=ws(x), w2=ws(f), xx=son[x][!w1];
        if(!isroot(f))son[ff][w2]=x;son[x][!w1]=f;son[f][w1]=xx;
        if(xx)fa[xx]=f;fa[f]=x;fa[x]=ff;
        update(f);
    }
    void splay(int x){
        int f=x,z=0;
        st[++z]=f;
        while(!isroot(f)) st[++z]=f=fa[f];
        while(z) pushdown(st[z--]);
        for(;!isroot(x);rot(x))
            if(!isroot(fa[x])&&ws(x)==ws(fa[x])) rot(fa[x]);
        update(x);
    }
    void access(int x){
        for(int y=0;x;x=fa[y=x]){
            splay(x), rc=y; update(x);
        }
    }
    void makeroot(int x){
        access(x); splay(x);
        rev(x);
    } 
    int findroot(int x){
        access(x); splay(x);
        while(lc) pushdown(x),x=lc;
        return x;
    }
    void split(int x,int y){ //提取路径
        makeroot(x);
        access(y); splay(y); 
    }
    void link(int x,int y){ //把x的爸爸设为y 
        makeroot(x);
        if(findroot(y)!=x) fa[x]=y;
    }
    void cut(int x,int y){
        makeroot(x);
        if(findroot(y)==x&&fa[x]==y&&!rc){
            fa[x]=son[y][0]=0; update(y);
        }
    }
    
    int main(){
        int n,m,i,op,x,y;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        while(m--){
            scanf("%d%d%d",&op,&x,&y);
            if(op==0) split(x,y),printf("%d
    ",s[y]);
            if(op==1) link(x,y);
            if(op==2) cut(x,y);
            if(op==3) splay(x),v[x]=y;
        }
        return 0;
    }
  • 相关阅读:
    剑指Offer47 不用加减乘除做加法
    剑指Offer46 求1+2+...+n
    剑指Offer45 约瑟夫环
    剑指Offer44 扑克牌的顺子
    剑指Offer43 n个骰子点数概率
    面试题分享
    初识python版本
    redis安装部署
    配置本地yum源
    闭包、装饰器
  • 原文地址:https://www.cnblogs.com/noblex/p/9096253.html
Copyright © 2011-2022 走看看