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

题目

luogu3690

硫硼作者想提醒大家,WA 了 TLE 了 RE 了的,也许只是主函数写错了

image

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;

#define pa T[x].fa
#define l T[x].ch[0]
#define r T[x].ch[1]
const int N=300005;

struct lct
{
    struct node
    {
        int ch[2],fa,sum,rev,w;//sum记录以当前节点为根的辅助树的权值和 
    }T[N];
    bool son(int x){return T[pa].ch[1]==x;}//判断是否为右儿子 
    bool isroot(int x){return T[pa].ch[0]!=x&&T[pa].ch[1]!=x;}//判断节点x是否为所处辅助树的根
    //每个辅助树之间是有连接的,即儿子都认父亲,父亲只认重儿子,所以当其父亲左右儿子都不为自己时,当前节点为所处辅助树的根 
    void reverse(int x){T[x].rev^=1;swap(l,r);}//翻转
    void update(int x){T[x].sum=T[l].sum^T[r].sum^T[x].w;}//异或 
    void pushdown_once(int x)//下传翻转标记 
    {
        if(!T[x].rev) return;
        if(l) reverse(l); if(r) reverse(r);
        T[x].rev=0;
    }
    void pushdown(int x){if(!isroot(x)) pushdown(pa);pushdown_once(x);}//从上往下翻转 
    void lk(int x,int y,int f)
    {
        T[x].ch[f]=y;
        T[y].fa=x;
    }
    void rotate(int x)
    {
        int y=T[x].fa,z=T[y].fa,f=son(x);
        if(!isroot(y)) T[z].ch[son(y)]=x;T[x].fa=z;//如果是根,儿子认父亲,父亲不认儿子 
        T[y].ch[f]=T[x].ch[f^1];T[T[x].ch[f^1]].fa=y; 
        T[x].ch[f^1]=y;T[y].fa=x;
        update(y);update(x);
    }  
    void splay(int x)//将x转至根 
    {
        pushdown(x);
        while(!isroot(x))
        {
            if(!isroot(pa)) rotate(son(pa)==son(x)? pa:x);
            rotate(x);
        }
    }
    /***/
    void access(int x){for(int y=0;x;y=x,x=pa) splay(x),r=y,update(x);}//将当前节点至根的路径修改为一条重链
    void makeroot(int x){access(x);splay(x);reverse(x);}//将x换为原树的根 
    int findroot(int x)//查询节点x所在树的根 
    {
        access(x);splay(x);
        while(l) pushdown_once(x),x=l;return x;
    }
    void link(int x,int y){makeroot(x);T[x].fa=y;}//将x接在y下方(反着接也可以)
    void cut(int x,int y)//断开x,y的连接 
    {
        makeroot(x);access(y);splay(y);
        T[x].fa=T[y].ch[0]=0;update(y);
    }
    void split(int x,int y){makeroot(x);access(y);splay(y);}
}st;

int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&st.T[i].w);
    for(int i=1;i<=m;i++)
    {
        int opt,x,y;scanf("%d%d%d",&opt,&x,&y);
        if(opt==0) st.split(x,y),printf("%d\n",st.T[y].sum);
        if(opt==1) if (st.findroot(x)!=st.findroot(y)) st.link(x,y);
        if(opt==2) if (st.findroot(x)==st.findroot(y)) st.cut(x,y);
        if(opt==3) st.T[x].w=y,st.splay(x);
    }
    return 0;
}
posted @ 2017-11-18 16:29  XYZinc  阅读(231)  评论(0编辑  收藏  举报