动态树模板

Link Cut Tree:

#include<bits/stdc++.h>
#define L(x) T[(x)].son[0]
#define R(x) T[(x)].son[1]
#define fa(x) T[(x)].fa
using namespace std;
const int N=300050;
int stk[N];
int n,m;
struct Tree{
    int son[2],fa;
    int val,siz,Xor;
    bool tag;
}T[N];
bool isroot(int x){
    return (L(fa(x))==x||R(fa(x))==x)==0;
}
void pushup(int x){
    T[x].Xor=T[L(x)].Xor^T[R(x)].Xor^T[x].val;
    return;
}
void rev(int x){
    swap(L(x),R(x));
    T[x].tag^=1;
}
void pushdown(int x){
    if(T[x].tag){
        if(L(x))rev(L(x));
        if(R(x))rev(R(x));
        T[x].tag=0;
    }
}
bool identify(int x){
    return L(fa(x))==x?0:1;
}
void connect(int x,int fa,int son){
    fa(x)=fa;
    T[fa].son[son]=x;
}
//以下Splay与普通的Splay有若干处不同 
void rotate(int x){
    int y=fa(x);
    int z=fa(y);
    int zson=identify(y);
    int yson=identify(x);
    int xson=T[x].son[yson^1];
    fa(x)=fa(y);//将x的父亲设成y的父亲:区别1 
    if(!isroot(y))connect(x,z,zson);//判y,转的顺序不同:区别2 
    connect(xson,y,yson);
    connect(y,x,yson^1);
    pushup(y);
    pushup(x);
    return ;
}
void splay(int x){//传一个参:区别3
    int tp=0,y=x;
    stk[++tp]=y;
    while(!isroot(y))stk[++tp]=y=fa(y);
    while(tp)pushdown(stk[tp--]);//存路径推标记:区别4 
    while(!isroot(x)){
        int fa=fa(x);
        if(!isroot(fa)){//判y:区别5
            if(identify(x)!=identify(fa)){
                rotate(x);
            }else{
                rotate(fa);
            }
        }
        rotate(x);
    }//无换根:区别6
}
void access(int x){
    for(int y=0;x;y=x,x=fa(x)){
        splay(x);
        R(x)=y;
        pushup(x);
    }
}
void makeroot(int x){
    access(x);
    splay(x);
    rev(x);
}
int findroot(int x){
    access(x);
    splay(x);
    while(L(x)){
        pushdown(x);
        x=L(x);
    }
    splay(x);
    return x;
}
void split(int x,int y){
    makeroot(x);
    access(y);
    splay(y);
}
void link(int x,int y){
    makeroot(x);
    if(findroot(y)==x)return;
    fa(x)=y;
}
void cut(int x,int y){
    makeroot(x);
    if(findroot(y)!=x||fa(y)!=x||L(y))return;
    fa(y)=R(x)=0;
    pushup(x);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&T[i].val);
    }
    for(int i=1;i<=m;i++){
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        if(opt==0){
            split(x,y);
            printf("%d\n",T[y].Xor);
        }else if(opt==1){
            link(x,y);
        }else if(opt==2){
            cut(x,y);
        }else if(opt==3){
            splay(x);
            T[x].val=y;
        }
    }
} 
LCT

其他动态树待补

posted @ 2020-02-02 22:16  passione  阅读(137)  评论(0编辑  收藏  举报