[模板]动态树 Link-cut Tree

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define reg register
inline int read() {
    int res = 0;char ch = getchar();bool fu = 0;
    while(!isdigit(ch)) fu |= (ch == '-'), ch = getchar();
    while(isdigit(ch)) res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
    return fu ? - res : res;
}
#define int long long

namespace BriMon 
{

#define N 300005
int n, m;
int val[N], ch[N][2], fa[N], rev[N], tr[N];

inline int whois(int x) {return ch[fa[x]][1] == x;}
inline int isr(int x) {return ch[fa[x]][0] != x and ch[fa[x]][1] != x;}
inline void upd(int x) {tr[x] = tr[ch[x][0]] ^ tr[ch[x][1]] ^ val[x];}
inline void rever(int x) {rev[x] ^= 1, swap(ch[x][0], ch[x][1]);}
inline void pushdown(int x) {
    if (rev[x]) {
        rev[x] = 0;
        if (ch[x][0]) rever(ch[x][0]);
        if (ch[x][1]) rever(ch[x][1]);
    }
}
inline void pd(int x) {if (!isr(x)) pd(fa[x]);pushdown(x);}
inline void rot(int x) {
    int y = fa[x], z = fa[y], d = whois(x);
    if (!isr(y)) ch[z][whois(y)] = x;fa[x] = z;
    ch[y][d] = ch[x][d ^ 1], fa[ch[x][d ^ 1]] = y;
    ch[x][d ^ 1] = y, fa[y] = x;
    upd(y), upd(x);
}
inline void splay(int x) {
    pd(x);
    for ( ; !isr(x) ; rot(x)) if (!isr(fa[x])) rot(ch[fa[fa[x]]][1] == fa[x] and ch[fa[x]][1] == x ? fa[x] : x);
}
inline void access(int x) {
    for (reg int y = 0 ; x ; y = x, x = fa[x]) splay(x), ch[x][1] = y, upd(x);
}
inline void makr(int x) {
    access(x), splay(x);
    rever(x);
}
inline int findr(int x) {
    access(x), splay(x);
    while(ch[x][0]) pushdown(x), x = ch[x][0];
    return x;
}
inline void link(int x, int y) {makr(x), fa[x] = y;}
inline void cut(int x, int y) {
    makr(x);
    if (findr(y) != x or fa[x] != y or ch[x][1]) return ;
    fa[x] = 0, ch[y][0] = 0, upd(y);
}
inline void split(int x, int y) {
    makr(x), access(y), splay(y);
}

int main()
{
    n = read(), m = read();
    for (reg int i = 1 ; i <= n ; i ++) val[i] = read();
    while(m --) {
        int opt = read(), x = read(), y = read();
        if (opt == 0) split(x, y), printf("%lld\n", tr[y]);
        else if (opt == 1) {if (findr(x) != findr(y)) link(x, y);}
        else if (opt == 2) {if (findr(x) == findr(y)) cut(x, y);}
        else splay(x), val[x]=y;
    }
    return 0;
}

}
int zZh = BriMon :: main();
signed main() {return 0;}

猜你喜欢

转载自www.cnblogs.com/BriMon/p/10127349.html
今日推荐