lct 維護有根樹的實鏈剖分, 就像重鏈剖分一樣, 每個點都有一個實兒子和一堆虛兒子。
lct 的每個實鏈都用一顆獨立的 splay 來維護, 節點都是原鏈中的節點編號, 滿足二叉查找樹性質的 key 值是節點在原樹中的深度。另外,對於原樹中的節點 x,若其在原樹中的父親的實兒子不是 x, 那麼在 lct 中, x 所在的實鏈的 splay 的根的父節點指向 x 在原樹的父親, 另外,由於 splay 維護的是實鏈的信息, 那麼 x 父親並不會把 x 當作 splay 的子節點, 這就是 “認父不認子”。
lct 有一個操作 access,它是 lct 的一些特色操作的基礎。access (x) 表示將原樹中的根 root 到 x 的路徑劃分成一個獨立的實鏈, 這個操作由於認父不認子很好實現。
【LCT模板】
模板革新!
模板
【記錄】
精彩摘選:(論短路運算符和下標運算符的用法)
const int MAXN = 1e5 + 5 ;
int n, m, a[MAXN] ;
int s[MAXN], pa[MAXN], ch[MAXN][2] ;
// xor_sum parent children
bool tag[MAXN] ;
inline bool is(int x) { return x[pa][ch][0] != x && x[pa][ch][1] != x;} // isroot?
inline void ud(int x) { x[s] = x[a] ^ x[ch][0][s] ^ x[ch][1][s];}// update
inline void rv(int x) {x[tag] ^= 1, std::swap(x[ch][0], x[ch][1]); }// reverse
inline void ps(int x) { x[tag] && (rv(x[ch][0]), rv(x[ch][1]), x[tag] = 0);}
// pushdown