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

人生第一颗动态树
动态树就是类似树链剖分的利用splay森林维护树上一些链的操作
因为虚实链可以变化,所以叫做动态树
然后因为是splay森林,所以判断是否存在g时应当使用isroot(f)而不是g==0
然后是常规的splay操作
link和cut时注意判断合法
上代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct SNode{
    int son[2],tag,val,sum;
}SPT[300100];
int fa[300100],sta[300100],topc,n,m;
void pushup(int o){
    SPT[o].sum=SPT[SPT[o].son[0]].sum^SPT[o].val^SPT[SPT[o].son[1]].sum;
}
void pushdown(int o){
    if(o&&SPT[o].tag){
        swap(SPT[o].son[0],SPT[o].son[1]);
        SPT[SPT[o].son[0]].tag^=1;
        SPT[SPT[o].son[1]].tag^=1;
        SPT[o].tag=0;
    }
}
bool isroot(int o){
    return (SPT[fa[o]].son[0]!=o)&&(SPT[fa[o]].son[1]!=o);
}
bool isrl(int o){//true right false left
    return SPT[fa[o]].son[1]==o;
}
void rorate(int o){
    if(isroot(o))
        return;
    int f=fa[o];
    int g=fa[f];
    int which=isrl(o);
    pushdown(f);
    pushdown(o);
    fa[o]=g;
    if(!isroot(f))
        SPT[g].son[SPT[g].son[1]==f]=o;
    SPT[f].son[which]=SPT[o].son[which^1];
    fa[SPT[o].son[which^1]]=f;
    SPT[o].son[which^1]=f;
    fa[f]=o;
    pushup(f);
    pushup(o);
}
void splay(int o){
    topc=0;
    int y=o;
    sta[++topc]=y;
    while(!isroot(y)){
        sta[++topc]=fa[y];
        y=fa[y];
    }
    for(int i=topc;i>=1;i--)
        pushdown(sta[i]);
    for(int f;!isroot(o);rorate(o)){
        if(!isroot(f=fa[o]))
            rorate((isrl(f)==isrl(o))?f:o);
    }
}
void access(int o){
    for(int y=0;o;o=fa[y=o]){
        splay(o),SPT[o].son[1]=y,pushup(o);
    }
}
void makeroot(int o){
    access(o);
    splay(o);
    // printf("ok\n");
    SPT[o].tag^=1;
    pushdown(o);
}
int findroot(int o){
    access(o);
    splay(o);
    pushdown(o);
    while(SPT[o].son[0])
        pushdown(o=SPT[o].son[0]);
    return o;
}
void split(int x,int y){
    // printf("ok\n");
    makeroot(x);
    access(y);
    // printf("ok!\n");
    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){//dep[x]<dep[y]
    makeroot(x);
    if(findroot(y)==x&&fa[x]==y&&SPT[y].son[0]==x&&SPT[x].son[1]==0)
        fa[x]=0,SPT[y].son[0]=0,pushup(y);
}
int query(int x,int y){
    split(x,y);
    return SPT[y].sum;
}
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&SPT[i].val),SPT[i].sum=SPT[i].val;
    for(int i=1;i<=m;i++){
        int opt,x,y;
        scanf("%d %d %d",&opt,&x,&y);
        if(opt==0)
            printf("%d\n",query(x,y));
        else if(opt==1)
            link(x,y);
        else if(opt==2)
            cut(x,y);
        else
            splay(x),SPT[x].val=y;
    }
    return 0;
}
posted @ 2018-12-03 10:33  dreagonm  阅读(154)  评论(0编辑  收藏  举报