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

https://www.luogu.com.cn/problem/P3690

\(LCT\)

\(LCT\)需要通过\(Splay\)来维护,每一个\(Splay\)对应的是原树的一条链,\(Splay\)中父子关系与原树不同

\(Splay\)节点除了标记以外,维护的有:

\(ch_0:\)左儿子,代表原树中深度中深度比该节点小的节点(因为在链上,所以代表其祖先)

\(ch_1:\)右儿子,代表原树中深度中深度比该节点大的节点(因为在链上,所以代表其子孙)

\(f:\)父亲,对于在\(Splay\)中的非根节点,其\(f\)就是\(Splay\)中的父亲,对于在\(Splay\)中的根节点,其父亲就是这条链在原树中的父亲

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 100005
#define ls(x) a[x].ch[0]
#define rs(x) a[x].ch[1]
#define fa(x) a[x].f
#define v(x) a[x].val
#define s(x) a[x].xsum
#define tag(x) a[x].lazy
#define id(x) ((ls(fa(x))==x)?0:1)
using namespace std;
int n,m,opt,x,y,q[N];
struct node
{
    int ch[2],f,val,xsum;
    bool lazy;
}a[N];
void update(int x)
{
    s(x)=s(ls(x))^s(rs(x))^v(x);
}
void pushdown(int x)
{
    if (!tag(x))
        return;
    tag(ls(x))^=1;
    tag(rs(x))^=1;
    swap(ls(x),rs(x));
    tag(x)=0;
}
void connect(int x,int F,int son)
{
    fa(x)=F;
    a[F].ch[son]=x;
}
bool isrt(int x)
{
    return ls(fa(x))!=x && rs(fa(x))!=x;
}
void rot(int x)
{
    int y=fa(x),r=fa(y);
    int yson=id(x),rson=id(y);
    if (!isrt(y))
        connect(x,r,rson); else
        fa(x)=r;
    connect(a[x].ch[yson^1],y,yson);
    connect(y,x,yson^1);
    update(y),update(x);
}
void splay(int x)
{
    int g=x,k=0;
    q[++k]=g;
    while (!isrt(g))
    {
        g=fa(g);
        q[++k]=g;
    }
    while (k)
        pushdown(q[k--]);
    while (!isrt(x))
    {
        int y=fa(x);
        if (isrt(y))
            rot(x); else
        if (id(x)==id(y))
            rot(y),rot(x); else
            rot(x),rot(x);
    }
}
void access(int x)
{
    for (int y=0;x;y=x,x=fa(x))
    {
        splay(x);
        rs(x)=y;
        update(x);
    }
}
void makeroot(int x)
{
    access(x);
    splay(x);
    tag(x)^=1;
    pushdown(x);
}
int findroot(int x)
{
    access(x);
    splay(x);
    pushdown(x);
    while (ls(x))
    {
        x=ls(x);
        pushdown(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 && !ls(y))
    {
        fa(y)=rs(x)=0;
        update(x);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
        scanf("%d",&v(i)),s(i)=v(i);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&opt,&x,&y);
        if (opt==0)
        {
            split(x,y);
            printf("%d\n",s(y));
        } else
        if (opt==1)
            link(x,y); else
        if (opt==2)
            cut(x,y); else
            {
                splay(x);
                v(x)=y;
                update(x);
            }
    }
    return 0;
}
posted @ 2020-08-10 08:40  GK0328  阅读(72)  评论(0编辑  收藏  举报