板题,只放代码。

const int N = 3e5 + 5;

inline ll Read() {
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

namespace Main {
	struct LCT {
		int ch[N][2], fa[N], siz[N], val[N], sum[N], rev[N];
		int get(int p) { return ch[fa[p]][1] == p; }
		bool notroot(int p) { return ch[fa[p]][0] == p || ch[fa[p]][1] == p; }
		void pushup (int p) { sum[p] = sum[ch[p][0]] ^ sum[ch[p][1]] ^ val[p]; }
		void pushrev (int p) { rev[p] ^= 1; }
		void pushdown (int p) {
			if (!rev[p]) return;
			swap(ch[p][0], ch[p][1]); 
			if (ch[p][0]) pushrev(ch[p][0]);
			if (ch[p][1]) pushrev(ch[p][1]);
			rev[p] = 0;
		}
		void rotate (int x) {
			int y = fa[x], z = fa[y];
			int k = get(x), w = ch[x][k ^ 1];
			if (notroot(y)) ch[z][get(y)] = x;
			ch[x][k ^ 1] = y; ch[y][k] = w;
			if (w) fa[w] = y; fa[y] = x; fa[x] = z;
			pushup(y);
		}

		int st[N];
		void splay (int x) {
			int y = x, top = 0; st[++top] = y;
			for (; notroot(y); y = fa[y]) st[++top] = fa[y];
			for (; top; top--) pushdown(st[top]);
			for (; notroot(x); rotate(x)) {
				if (notroot(fa[x])) rotate(get(x) == get(fa[x])? fa[x]: x);
			}
			pushup(x);
		}
		void access (int x) {
			for (int y = 0; x; y = x, x = fa[x]) {
				splay (x); ch[x][1] = y;
				pushup (x);
			}
		}
		void makeroot (int p) { access(p); splay(p); pushrev(p); }
		void split (int p, int q) { makeroot(p); access(q); splay(q); }
		void link (int p, int q) { split(p, q); fa[p] = q; }
		void cut (int p, int q) { 
			split(p, q);
			if (fa[p] != q) return;
			ch[q][0] = fa[p] = 0;
			pushup(q);
		}
		int query (int p, int q) { split(p, q); return sum[q]; }
	}t;
	int n, q;
	int main () {
		n = Read(), q = Read();
		for (int i = 1; i <= n; i++) t.val[i] = Read();
		for (; q--; ) {
			int op = Read(), u = Read(), v = Read();
			if(op == 0) printf("%d\n", t.query(u, v));
			if(op == 1) t.link(u, v);
			if(op == 2) t.cut(u, v);
			if(op == 3) t.splay(u), t.val[u]=v;
		}
		return 0;
	}
}

int main () {
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	Main::main();
	return 0;
}
EOF

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。

博客信息

作者
Jayun
时间
2023-11-14 21:40:39
博客类型