题目大意:给定$n$个点以及每个点的权值,要你处理接下来的$m$个操作。操作有$4$种。操作从$0到3编号。点从1到n编号。
- $0,x,y$:代表询问从$x$到$y$的路径上的点的权值的$xor$和。保证$x$到$y$是联通的。
- $1,x,y$:代表连接$x$到$y$,若$x$到$y$已经联通则无需连接。
- $2,x,y$:代表删除边$(x,y)$,不保证边$(x,y)$存在。
- $3,x,y$:代表将点$x$上的权值变成$y$。
题解:$LCT$
卡点:无
C++ Code:
#include <cstdio> #define maxn 300010 #define lc(rt) son[rt][0] #define rc(rt) son[rt][1] using namespace std; int n, m; int V[maxn], s[maxn]; int son[maxn][2], tg[maxn], fa[maxn]; inline void swap(int &a, int &b) {a ^= b ^= a ^= b;} inline void swap(int rt) {swap(lc(rt), rc(rt));} inline int get(int rt, int flag = 1) {return son[fa[rt]][flag] == rt;} inline bool is_root(int rt) {return !(get(rt, 0) || get(rt));} inline void pushdown(int rt) { swap(rt); tg[lc(rt)] ^= 1, tg[rc(rt)] ^= 1, tg[rt] ^= 1; } inline void update(int rt) {s[rt] = s[lc(rt)] ^ s[rc(rt)] ^ V[rt];} inline void rotate(int x) { int y = fa[x], z = fa[y], b = get(x); if (!is_root(y)) son[z][get(y)] = x; fa[son[y][b] = son[x][!b]] = y; son[x][!b] = y; fa[y] = x; fa[x] = z; update(y); update(x); } int stack[maxn], top; inline void splay(int x) { stack[top = 1] = x; for (int y = x; !is_root(y); stack[++top] = y = fa[y]); for (; top; top--) if (tg[stack[top]]) pushdown(stack[top]); for (; !is_root(x); rotate(x)) if (!is_root(fa[x])) get(x) ^ get(fa[x]) ? rotate(x) : rotate(fa[x]); update(x); } inline void access(int rt) {for (int t = 0; rt; rc(rt) = t, t = rt, rt = fa[rt]) splay(rt);} inline void make_root(int rt) {access(rt), splay(rt), tg[rt] ^= 1;} inline void link(int x, int y) {make_root(x); fa[x] = y;} inline void cut(int x, int y) {make_root(x); access(y); splay(y); fa[x] = lc(y) = 0;} inline bool connect(int x, int y) { make_root(x); access(y); splay(y); return fa[x] == y; } inline bool uni(int x, int y) { make_root(x); access(y); splay(y); int tmp = x; while (tmp) tmp = fa[tmp]; return tmp == y; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%d", &V[i]); s[i] = V[i]; } while (m --> 0) { int op, x, y; scanf("%d%d%d", &op, &x, &y); if (op == 0) { make_root(x); access(y); splay(y); printf("%d ", s[y]); } if (op == 1) if (!uni(x, y)) link(x, y); if (op == 2) if (connect(x, y)) cut(x, y); if (op == 3) { access(x); splay(x); V[x] = y; update(x); } } return 0; }