前置知识:Splay和文艺平衡树
介绍
Link Cut Tree,简称LCT,
时间复杂度分析
细节
原splay函数
Rotate()中,注意son[z][]
的赋值要有限制语句isroot(y)
,因为z可能是“认父亲不认儿子”的splay根节点的父亲(Splay()中的限制管不到,因为Splay()只考虑父亲,但Rotate()要考虑爷爷)
void Rotate(int x) {
int y=fa[x],z=fa[fa[x]];
bool dx=dir(x),dy=dir(y);
son[y][dx]=son[x][!dx];
if(!isroot(y)) son[z][dy]=x; //注意特判
fa[x]=z; fa[y]=x;
fa[son[x][!dx]]=y;
son[x][!dx]=y;
Pushup(y); Pushup(x);
}
Splay()前,用Update(x)从该splay树的根到x依次Pushdown(),保证方向正确(文艺平衡树有解释)
void Update(int x) {
if(!isroot(x)) Update(fa[x]);
Pushdown(x); //用递归写
}
LCT特有函数
连续的Access(x),Access(y),返回值(最后一次并入的虚节点)为LCA(x,y)(x,y连通时),必要时可获取返回值
Access(x)会使x失去右儿子,这使得Split(x,y)会形成一棵根为y,最左边叶子为x,且y无右儿子的树
Link()用Makeroot()和Findroot()判连通
Cut()可以用set快速判边的存在性