动态树

2024-08-15

以Splay树为基础,构建动态树,便于实现动态变化的树和森林

#include <bits/stdc++.h>
#define io cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define LL long long
#define ULL unsigned long long
#define EPS 1e-8
#define INF 0x7fffffff
#define SUB -INF - 1
using namespace std;
const int N = 300005;
struct node
{
    int fa, ch[2], sum, val, lazy;
} t[N];
#define lc t[x].ch[0]
#define rc t[x].ch[1]
bool isRoot(int x)
{
    int g = t[x].fa;
    return t[g].ch[0] != x && t[g].ch[1] != x;
}
void pushup(int x)
{
    t[x].sum = t[x].val ^ t[lc].sum ^ t[rc].sum;
}
void reverse(int x)
{
    if (!x)
        return;
    swap(lc, rc);
    t[x].lazy ^= 1;
}
void pushdown(int x)
{
    if (t[x].lazy)
    {
        reverse(lc);
        reverse(rc);
        t[x].lazy = 0;
    }
}
void push(int x)
{
    if (!isRoot(x))
        push(t[x].fa);
    pushdown(x);
}
void rotate(int x)
{
    int y = t[x].fa;
    int z = t[y].fa;
    int k = t[y].ch[1] == x;
    if (!isRoot(y))
        t[z].ch[t[z].ch[1] == y] = x;
    t[x].fa = z;
    t[y].ch[k] = t[x].ch[k ^ 1];
    if (t[x].ch[k ^ 1])
        t[t[x].ch[k ^ 1]].fa = y;
    t[y].fa = x;
    t[x].ch[k ^ 1] = y;
    pushup(y);
}
void splay(int x)
{
    int y, z;
    push(x);
    while (!isRoot(x))
    {
        y = t[x].fa, z = t[y].fa;
        if (!isRoot(y))
            (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
        rotate(x);
    }
    pushup(x);
}
void access(int x)
{
    for (int child = 0; x; child = x, x = t[x].fa)
    {
        splay(x);
        rc = child;
        pushup(x);
    }
}
void makeroot(int x)
{
    access(x);
    splay(x);
    reverse(x);
}
void split(int x, int y)
{
    makeroot(x);
    access(y);
    splay(y);
}
void link(int x, int y)
{
    makeroot(x);
    t[x].fa = y;
}
void cut(int x, int y)
{
    split(x, y);
    if (t[y].ch[0] != x || rc)
        return;
    t[x].fa = t[y].ch[0] = 0;
    pushup(x);
}
int findroot(int x)
{
    access(x);
    splay(x);
    while (lc)
        pushdown(x), x = lc;
    return x;
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &t[i].val);
        t[i].sum = t[i].val;
    }
    while (m--)
    {
        int opt, a, b;
        scanf("%d%d%d", &opt, &a, &b);
        switch (opt)
        {
        case 0:
            split(a, b);
            printf("%d\n", t[b].sum);
            break;
        case 1:
            if (findroot(a) != findroot(b))
                link(a, b);
            break;
        case 2:
            cut(a, b);
            break;
        case 3:
            splay(a);
            t[a].val = b;
            break;
        }
    }
    return 0;
}