【模板】LCT

#include <bits/stdc++.h>
#define il inline
#define re register
#define gc getchar()
#define maxn 300005
#define ls ch[x][0]
#define rs ch[x][1]
using namespace std;

il int read() {
	re int ret = 0, f = 1; char c = gc;
	while (!isdigit(c)) { if (c == '-') f = -1; c = gc; }
	while (isdigit(c)) { ret = (ret << 1) + (ret << 3) + (c ^ 48); c = gc; }
	return ret * f;
}

int f[maxn], ch[maxn][2], v[maxn], t[maxn], st[maxn], r[maxn];
il bool nrt(re int x) {
	return ch[f[x]][0] == x || ch[f[x]][1] == x;
}

il void pushup(re int x) {
	t[x] = t[ls] ^ t[rs] ^ v[x];
}

il void rev(re int x) {
	re int t = ls; ls = rs; rs = t;
	r[x] ^= 1;
}

il void pushdown(re int x) {
	if (!r[x]) return;
	if (ls) rev(ls);
	if (rs) rev(rs);
	r[x] = 0;
}

il void rotate(re int x) {
	re int y = f[x], z = f[y], chk = ch[y][1] == x, w = ch[x][chk ^ 1];
	if (nrt(y)) ch[z][ch[z][1] == y] = x; ch[x][chk ^ 1] = y; ch[y][chk] = w;
	if (w) f[w] = y, f[y] = x, f[x] = z;
	pushup(y);
}

il void splay(re int x) {
	re int y = x, z = 0;
	st[++z] = y;
	while (nrt(y)) st[++z] = y = f[y];
	while (z) pushdown(st[z--]);
	while (nrt(x)) {
		y = f[x], z = f[y];
		if (nrt(y))
			rotate((ch[y][0] == x) ^ (ch[z][0] == y) ? x : y);
		rotate(x);
	}
	pushup(x);
}

il void access(re int x) {
	for (re int y = 0; x; x = f[y = x])
		splay(x), rs = y, pushup(x);
}

il void mrt(re int x) {
	access(x); splay(x); rev(x);
}

il int frt(re int x) {
	access(x); splay(x);
	while (ls) pushdown(x), x = ls;
	splay(x);
	return x;
}

il void split(re int x, re int y) {
	mrt(x);	access(y); splay(y);
}

il void link(re int x, re int y) {
	mrt(x); if (frt(y) != x) f[x] = y;
}

il void cut(re int x, re int y) {
	mrt(x);
	if (frt(y) == x && f[y] == x && !ch[y][0]) {
		f[y] = ch[x][1] = 0;
		pushup(x);
	}
}

int n, m, opt, x, y;
int main() {
	n = read(), m = read();
	for (re int i = 1; i <= n; i++) v[i] = read();
	while (m--) {
		opt = read(), x = read(), y = read();
		if (opt == 0)
			split(x, y), printf("%d\n", t[y]);
		else if (opt == 1)
			link(x, y);
		else if (opt == 2)
			cut(x, y);
		else
			splay(x), v[x] = y;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值