救救孩子吧
  • 板块灌水区
  • 楼主Zigh_Wang
  • 当前回复3
  • 已保存回复3
  • 发布时间2022/6/28 20:48
  • 上次更新2023/10/27 22:23:44
查看原帖
救救孩子吧
164883
Zigh_Wang楼主2022/6/28 20:48

LCT板子第11个点一直T

也不是死循环,就是很正经的T

调了一个下午了TAT

#include<bits/stdc++.h>
#define ls(x) son[x][0]
#define rs(x) son[x][1]
using namespace std;

const int MAXN = 1e5 + 5;

int inpt()
{
	int x = 0, f = 1;
	char ch;
	for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
	if(ch == '-'){
		f = -1;
		ch = getchar();
	}
	do{
		x = (x << 3) + (x << 1) + ch - '0';
		ch = getchar();
	}while(ch >= '0' && ch <= '9');
	return x * f;
}

int n, m;
int w[MAXN];

int sta[MAXN];

struct LinkCutTree {
	struct SplayTree {
		int fa[MAXN];
		int son[MAXN][2];
		int xum[MAXN];//xor_sum
		int tag[MAXN];
	
		bool IsRoot(int x) {//x为当前伸展树的根 
			return son[fa[x]][0] != x && son[fa[x]][1] != x;
		}
		
		void Update(int x) {
			xum[x] = xum[ls(x)] ^ xum[rs(x)] ^ w[x];
		}
		
		void PushDown(int x) {
			if(tag[x]) {
				swap(ls(x), rs(x));
				if(ls(x)) {
					tag[ls(x)] ^= tag[x];
				}
				if(rs(x)) {
					tag[rs(x)] ^= tag[x];
				} 
				tag[x] = 0;
			}
		}
		
		void PushAll(int x) {
			if(!IsRoot(x)) {
				PushAll(fa[x]);
			}
			PushDown(x);
		}
		
		void Rotate(int x) {
			int y = fa[x], z = fa[y];
			int c = (son[y][0] != x);//如果x是y的左儿子,则值为0,刚好代表左儿子 
			son[y][c] = son[x][!c];
			fa[son[x][!c]] = y;
			fa[x] = z;
			if(!IsRoot(y)) {
				son[z][son[z][0] != y] = x;
			}
			son[x][!c] = y;
			fa[y] = x;
			
			Update(y);
			Update(x);//此顺序必定不能换 
		}
		
		void Splay(int x) {//将x旋转成根 
//			PushAll(x);
			
			int t = x, tp = 0;
			sta[++tp] = t;
			while(!IsRoot(t)) {
				t = fa[t];
				sta[++tp] = t;
			}
			while(tp) {
				PushDown(sta[tp]);
				tp--;
			}
		
			while(!IsRoot(x)) {
				int y = fa[x], z = fa[y];
				int cx = (son[y][0] != x), cy = (son[z][0] != y);
				if(IsRoot(y)) {
					Rotate(x);
					return ;
				}
				if(cx == cy) {
					Rotate(x);
					Rotate(x);
				}else {
					Rotate(y);
					Rotate(x);
				}
			}
		}
		
		void Reverse(int x) {
			tag[x] ^= 1;
		}
	}tr;
	
	void Access(int x) {//打通x到根的实链 
		for(int t = 0; x; t = x, x = tr.fa[x]) {
			tr.Splay(x);
			tr.son[x][1] = t;
			tr.Update(x);
		}
	}
	
	void MakeRoot(int x) {//使x变成原树的根 
		Access(x);
		tr.Splay(x);
		tr.Reverse(x);
	}
	
	int FindRoot(int x) {//找出x所在实链的根 
		Access(x);
		tr.Splay(x);
		while(tr.son[x][0]) {
			x = tr.son[x][0];
		}
		tr.Splay(x);
		return x; 
	}
	
	void Split(int x, int y) {//分离出x,y之间的路径为一条实链 (以y为根) 
		MakeRoot(x);
		Access(y);
		tr.Splay(y);
	}
	
	void Link(int x, int y) {//连接x和 y  
//		if(FindRoot(x) == FindRoot(y)) return ;
		MakeRoot(x);
		if(FindRoot(y) == x) return ;
		tr.fa[x] = y;//建一条虚边 
	}
	
	void Cut(int x, int y) {//断开x, y 
		Split(x, y);
		if(tr.son[y][0] != x || tr.son[x][1]) return ;
		tr.son[y][0] = tr.fa[tr.son[y][0]] = 0;
//		tr.Update(y);
	} 
	
	int Ask(int x, int y) {
		Split(x, y);
//		tr.Update(y);
		return tr.xum[y];
	}
	
	void Change(int x, int v) {
		tr.Splay(x);
		w[x] = v;
//		tr.Update(x);
	}
}LCT;

int main()
{
	freopen("P3690_11.in", "r", stdin);
	freopen("My.out", "w", stdout);
	
	n = inpt(), m = inpt();
	for(int i = 1; i <= n; i++) {
		w[i] = inpt();
	}
	
	for(int i = 1; i <= m; i++) {
//		cout << i << endl;
		
		int opt = inpt();
		int x = inpt(), y = inpt();
		if(opt == 0) {
			printf("%d\n", LCT.Ask(x, y));
			continue;
		}
		if(opt == 1) {
			LCT.Link(x, y);
			continue;
		}
		if(opt == 2) {
			LCT.Cut(x, y);
			continue;
		}
		if(opt == 3) {
			LCT.Change(x, y);
			continue;
		}
	} 
	
	return 0;
}
2022/6/28 20:48
加载中...