【MOBAN】一份普通的LCT动态树模板 P3690 【模板】动态树(Link Cut Tree)

LuoguP3690动态树

题目描述

给定 n 个点以及每个点的权值,要你处理接下来的 m 个操作。
操作有四种,操作从 03 编号。点从 1n 编号。

  • 0 x y 代表询问从 xy 的路径上的点的权值的 xor 和。保证 xy 是联通的。
  • 1 x y 代表连接 xy,若 xy 已经联通则无需连接。
  • 2 x y 代表删除边 (x,y),不保证边 (x,y) 存在。
  • 3 x y 代表将点 x 上的权值变成 y

输入格式

第一行两个整数,分别为 nm,代表点数和操作数。

接下来 n 行,每行一个整数,第 (i+1) 行的整数 ai 表示节点 i 的权值。

接下来 m 行,每行三个整数,分别代表操作类型和操作所需的量。

输出格式

对于每一个 0 号操作,你须输出一行一个整数,表示 xy 的路径上点权的 xor 和。

输入输出样例

输入 #1
3 3 
1
2
3
1 1 2
0 1 2 
0 1 1
输出 #1
3
1
输入 #2
5 14
114
514
19
19
810
1 1 2
0 1 2
2 1 2
1 1 2
1 2 3
2 1 3
1 1 3
1 4 5
1 2 5
0 3 5
0 3 4
3 5 233333
0 1 5
0 2 5
输出 #2
624
315
296
232709
232823

说明/提示

数据规模与约定

对于全部的测试点,保证:

  • 1≤n≤1051≤m≤3×1051≤ai≤109
  • 对于操作 0,1,2,保证 1≤x,y≤n
  • 对于操作 3,保证 1≤x≤n1≤y≤109
#include <bits/stdc++.h>

using namespace std;
const int maxn = 2e5 + 5;
int n, m;
int xo[maxn], sm[maxn], rev[maxn], fa[maxn];
int son[maxn][2];
static bool isroot(int x) { return son[fa[x]][0] != x && son[fa[x]][1] != x; }
void putup(int p) { sm[p] = xo[p] ^ sm[son[p][0]] ^ sm[son[p][1]]; }
void rotate(int x) {
    int y = fa[x];
    int z = fa[y];
    int k = (son[y][1] == x);
    if (!isroot(y)) {
        son[z][son[z][1] == y] = x;
    }
    fa[x] = z;
    son[y][k] = son[x][k ^ 1];
    fa[son[y][k]] = y;
    fa[y] = x;
    son[x][k ^ 1] = y;
    putup(y);
    putup(x);
}
void pushdown(int p) {
    if (!rev[p])
        return;
    swap(son[p][0], son[p][1]);
    rev[son[p][0]] ^= 1, rev[son[p][1]] ^= 1;
    rev[p] = 0;
}
int sta[maxn];
void splay(int x) {
    int top = 0;
    sta[++top] = x;
    for (int i = x; !isroot(i); i = fa[i]) {
        sta[++top] = fa[i];
    }
    while (top)
        pushdown(sta[top--]);
    while (!isroot(x)) {
        int y = fa[x], z = fa[y];
        if (!isroot(y))
            ((son[z][1] == y) ^ (son[y][1] == x)) ? rotate(x) : rotate(y);
        rotate(x);
    }
}
void acc(int x) {
    for (int y = 0; x; y = x, x = fa[x]) {
        splay(x);
        son[x][1] = y;
        putup(x);
    }
}
void setroot(int x) {
    acc(x);
    splay(x);
    rev[x] ^= 1;
}
void link(int x, int y) {
    setroot(x);
    fa[x] = y;
}
void cut(int x, int y) {
    setroot(x);
    acc(y);
    splay(y);
    son[y][0] = fa[x] = 0;
    putup(y);
}
int main() {
    //    freopen("P3690_8.in", "r", stdin);
    //    freopen("yo.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &xo[i]);
        sm[i] = xo[i];
    }
    int opt, x, y;
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d", &opt, &x, &y);
        if (opt == 0) {
            setroot(x);
            acc(y);
            splay(y);
            printf("%d\n", sm[y]);
        } else if (opt == 1) {
            setroot(x);
            acc(y);
            splay(y);
            int p = y;
            for (; son[p][0]; p = son[p][0])
                ;
            if (p == x)
                continue;
            link(x, y);
        } else if (opt == 2) {
            setroot(x);
            acc(y);
            splay(y);
            if (son[y][0] != x && son[y][1] != x)
                continue;
            cut(x, y);
        } else {
            acc(x);
            splay(x);
            xo[x] = y;
            putup(x);
        }
    }
    return 0;
}
posted @ 2021-12-01 21:14  Newuser233  阅读(39)  评论(0编辑  收藏  举报