题目大意:维护一种动态树形数据结构,支持:
1.求树上两点之间的点的异或和。
2.连接两点(不保证不连通)
3.删除连点之间的边(不保证两点联通)
4.将一个点的点权改成一个值
思路:还是LCT,思路也比较裸。主要是它各种不保证,所以要多加判断。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 300010 using namespace std; struct Complex{ int val,_xor; bool reverse; Complex *son[2],*father; Complex(int _val); void Reverse() { reverse ^= 1; swap(son[0],son[1]); } bool Check() { return father->son[1] == this; } void PushDown(); void PushUp(); }*tree[MAX],*nil = new Complex(0); Complex:: Complex(int _val) { val = _xor = _val; reverse = false; son[0] = son[1] = father = nil; } void Complex:: PushDown() { if(reverse) { son[0]->Reverse(); son[1]->Reverse(); reverse = false; } } void Complex:: PushUp() { _xor = son[0]->_xor ^ son[1]->_xor ^ val; } int points,asks; int src[MAX]; inline void Rotate(Complex *a,bool dir); inline void Splay(Complex *a); inline void PushPath(Complex *a); inline void Access(Complex *a); inline void ToRoot(Complex *a); inline void Link(Complex *x,Complex *y); inline void Cut(Complex *x,Complex *y); inline void Modify(Complex *a,int c); inline int Ask(Complex *x,Complex *y); inline Complex *FindRoot(Complex *x); int main() { cin >> points >> asks; for(int x,i = 1;i <= points; ++i) scanf("%d",&x),tree[i] = new Complex(x); for(int flag,x,y,i = 1;i <= asks; ++i) { scanf("%d%d%d",&flag,&x,&y); if(!flag) printf("%d\n",Ask(tree[x],tree[y])); else if(flag == 1) Link(tree[x],tree[y]); else if(flag == 2) Cut(tree[x],tree[y]); else Modify(tree[x],y); } return 0; } inline void Rotate(Complex *a,bool dir) { Complex *f = a->father; f->son[!dir] = a->son[dir]; f->son[!dir]->father = f; a->son[dir] = f; a->father = f->father; if(f->father->son[0] == f || f->father->son[1] == f) f->father->son[f->Check()] = a; f->father = a; f->PushUp(); } inline void Splay(Complex *a) { PushPath(a); while(a == a->father->son[0] || a == a->father->son[1]) { Complex *p = a->father->father; if(p->son[0] != a->father && p->son[1] != a->father) Rotate(a,!a->Check()); else if(!a->father->Check()) { if(!a->Check()) Rotate(a->father,true),Rotate(a,true); else Rotate(a,false),Rotate(a,true); } else { if(a->Check()) Rotate(a->father,false),Rotate(a,false); else Rotate(a,true),Rotate(a,false); } } a->PushUp(); } inline void PushPath(Complex *a) { static Complex *stack[MAX]; int top = 0; for(;a->father->son[0] == a || a->father->son[1] == a;a = a->father) stack[++top] = a; stack[++top] = a; while(top) stack[top--]->PushDown(); } inline void Access(Complex *a) { Complex *last = nil; while(a != nil) { Splay(a); a->son[1] = last; a->PushUp(); last = a; a = a->father; } } inline void ToRoot(Complex *a) { Access(a); Splay(a); a->Reverse(); } inline void Link(Complex *x,Complex *y) { if(FindRoot(x) == FindRoot(y)) return ; ToRoot(x); x->father = y; } inline void Cut(Complex *x,Complex *y) { if(x == y || FindRoot(x) != FindRoot(y)) return ; ToRoot(x); Access(y); Splay(y); if(y->son[0] != x) return ; y->son[0] = nil; x->father = nil; y->PushUp(); } inline Complex *FindRoot(Complex *a) { while(a->father != nil) a = a->father; return a; } inline void Modify(Complex *a,int c) { Splay(a); a->val = c; a->PushUp(); } inline int Ask(Complex *x,Complex *y) { ToRoot(x); Access(y); Splay(y); return y->_xor; }