LCT(动态树)

#include <bits/stdc++.h>
// #include <iostream>
// #include <cstring>
// #include <string>
// #include <algorithm>
// #include <cmath>
// #include <cstdio>
// #include <queue>
// #include <stack>
// #include <map>
// #include <bitset>
// #include <set>
// #include <vector>
// #include <iomanip>
#define ll long long
#define ull unsigned long long
#define met(a, b) memset(a, b, sizeof(a))
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define bep(i, a, b) for(int i = a; i >= b; --i)
#define lowbit(x) (x&(-x))
#define MID (l + r) / 2
#define ls pos*2
#define rs pos*2+1
#define ios() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;

const int N = 3e5 + 1010;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);

int fa[N], son[N][2], dp[N], tag[N];
int arr[N];

inline void pushup(int x) {
    dp[x] = dp[son[x][0]] ^ dp[son[x][1]] ^ arr[x];
}
inline void pushr(int x) {
    swap(son[x][0], son[x][1]);
    tag[x] ^= 1;
}
inline void pushdown(int x) {
    if(tag[x]) {
        pushr(son[x][0]);
        pushr(son[x][1]);
        tag[x] = 0;
    }
}
inline int nroot(int x) {
    return son[fa[x]][0] == x || son[fa[x]][1] == x;
}
inline void rotate(int x) {
    int y = fa[x], z = fa[y];
    int k = (son[y][1] == x);
    int t = son[x][!k];
    if(nroot(y)) son[z][son[z][1] == y] = x; // 与正常splay不一样,不能让这颗splay树的父亲认子,不然就变成了实边。
    son[x][!k] = y;
    son[y][k] = t;
    if(t) fa[t] = y;
    fa[y] = x;
    fa[x] = z;
    pushup(y);
}
inline void pushall(int x) {
    if(nroot(x)) pushall(fa[x]);
    pushdown(x);
}
inline void splay(int x) {
    int y, z;
    pushall(x);
    while(nroot(x)) {
        y = fa[x], z = fa[y];
        if(nroot(y)) {
            ((son[z][1] == y) == (son[y][1] == x)) ? rotate(y) : rotate(x);
        }
        rotate(x);
    }
    pushup(x);
}
inline void access(int x) {
    for(int y = 0; x; x = fa[y = x]) {
        splay(x);
        son[x][1] = y;
        pushup(x);
    }
}
inline void makeroot(int x) {
    access(x);
    splay(x);
    pushr(x);
}
inline void split(int x, int y) {
    makeroot(x);
    access(y);
    splay(y);
}
// 找该点所在数的根
inline int findroot(int x) {
    access(x);
    splay(x);
    while(son[x][0]) {
        pushdown(x);
        x = son[x][0];
    }
    splay(x);
    return x;
}
// 链接两点
inline void link(int x, int y) {
    makeroot(x);
    if(findroot(y) != x) fa[x] = y;
}
// 切断两点
inline void cut(int x, int y) {
    makeroot(x);
    if(findroot(y) == x && fa[y] == x && !son[y][0]) {
        fa[y] = son[x][1] = 0;
        pushup(x);
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    rep(i, 1, n) scanf("%d", &arr[i]);
    while(m--) {
        int op, x, y;
        scanf("%d%d%d", &op, &x, &y);
        switch(op) {
            case 0: split(x, y); printf("%d\n", dp[y]); break;
            case 1: link(x, y); break;
            case 2: cut(x, y); break;
            case 3: splay(x); arr[x] = y; break;
        }
    }
    return 0;
}
 

 

posted @ 2020-08-18 21:16  Ruby·Z  阅读(84)  评论(0)    收藏  举报