【学习笔记】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\n",s[y]);
        if(op==1) link(x,y);
        if(op==2) cut(x,y);
        if(op==3) splay(x),v[x]=y;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/noblex/p/9096253.html