link-cut tree

#define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] const int N = 5e5 + 100; struct Node{ int rev, rt; int son[2], pre; int mx, val, id; void init(){ rt = 1; rev = pre = son[0] = son[1] = 0; mx = val = id = 0; } }tr[N]; void Push_Rev(int x){ if(!x) return ; swap(lch(x), rch(x)); tr[x].rev ^= 1; } void Push_Up(int x){ if(!x) return ; tr[x].mx = tr[x].val, tr[x].id = x; if(tr[x].mx < tr[lch(x)].mx) tr[x].mx = tr[lch(x)].mx, tr[x].id = tr[lch(x)].id; if(tr[x].mx < tr[rch(x)].mx) tr[x].mx = tr[rch(x)].mx, tr[x].id = tr[rch(x)].id; } void Push_Down(int x){ if(tr[x].rev){ tr[x].rev = 0; Push_Rev(lch(x)); Push_Rev(rch(x)); } } void Rev(int x){ if(!tr[x].rt) Rev(tr[x].pre); Push_Down(x); } void rotate(int x){ if(tr[x].rt) return; int y = tr[x].pre, z = tr[y].pre; int k = (rch(y) == x); tr[y].son[k] = tr[x].son[k^1]; tr[tr[y].son[k]].pre = y; tr[x].son[k^1] = y; tr[y].pre = x; tr[x].pre = z; if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1; else tr[z].son[rch(z) == y] = x; Push_Up(y); } void Splay(int x){ Rev(x); while(!tr[x].rt){ int y = tr[x].pre, z = tr[y].pre; if(!tr[y].rt){ if(( x == rch(y) ) != (y == rch(z))) rotate(x); else rotate(y); } rotate(x); } Push_Up(x); } void Access(int x){ int y = 0; do{ Splay(x); tr[rch(x)].rt = 1; rch(x) = y; tr[y].rt = 0; Push_Up(x); y = x; x = tr[x].pre; }while(x); } void Make_rt(int x){ Access(x); Splay(x); Push_Rev(x); } bool judge(int u, int v){ while(tr[u].pre) u = tr[u].pre; while(tr[v].pre) v = tr[v].pre; return u == v; } void link(int u, int v){ Make_rt(u); tr[u].pre = v; } void cut(int u, int v){ Make_rt(u); Access(v); Splay(v); tr[lch(v)].pre = 0; tr[lch(v)].rt = 1; tr[v].pre = 0; lch(v) = 0; }
维护子树。
维护子树就是新开一个状态存一下 所有非偏爱子节点的信息, 然后每次access的时候我们就根据偏爱子节点的变化, 从而更新这个新开的状态。
这个写法 是维护 子树内的亦或和。
代码:

#define lch(x) tr[x].son[0] #define rch(x) tr[x].son[1] const int N = 5e5 + 100; struct Node{ int rev, rt; int son[2], pre; int sum, vsum, key; void init(){ rt = 1; rev = pre = son[0] = son[1] = 0; sum = vsum = key = 0; } }tr[N]; void Push_Rev(int x){ if(!x) return ; swap(lch(x), rch(x)); tr[x].rev ^= 1; } void Push_Up(int x){ if(!x) return ; tr[x].sum = tr[x].key ^ tr[lch(x)].sum ^ tr[rch(x)].sum ^ tr[x].vsum; } void Push_Down(int x){ if(tr[x].rev){ tr[x].rev = 0; Push_Rev(lch(x)); Push_Rev(rch(x)); } } void Rev(int x){ if(!tr[x].rt) Rev(tr[x].pre); Push_Down(x); } void rotate(int x){ if(tr[x].rt) return; int y = tr[x].pre, z = tr[y].pre; int k = (rch(y) == x); tr[y].son[k] = tr[x].son[k^1]; tr[tr[y].son[k]].pre = y; tr[x].son[k^1] = y; tr[y].pre = x; tr[x].pre = z; if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1; else tr[z].son[rch(z) == y] = x; Push_Up(y); } void Splay(int x){ Rev(x); while(!tr[x].rt){ int y = tr[x].pre, z = tr[y].pre; if(!tr[y].rt){ if(( x == rch(y) ) != (y == rch(z))) rotate(x); else rotate(y); } rotate(x); } Push_Up(x); } void Access(int x){ int y = 0; do{ Splay(x); tr[rch(x)].rt = 1; tr[x].vsum ^= tr[rch(x)].sum; rch(x) = y; tr[x].vsum ^= tr[rch(x)].sum; tr[y].rt = 0; Push_Up(x); y = x; x = tr[x].pre; }while(x); } void Make_rt(int x){ Access(x); Splay(x); Push_Rev(x); } void link(int u, int v){ Make_rt(u); Access(v); Splay(v); tr[u].pre = v; tr[v]. vsum ^= tr[u].sum; Push_Up(v); } void cut(int u, int v){ Make_rt(u); Access(v); Splay(v); tr[lch(v)].pre = 0; tr[lch(v)].rt = 1; tr[v].pre = 0; lch(v) = 0; Push_Up(v); }