Link-Cut Tree(LCT)

宏定义

  • #define pl a[p].ch[0]\texttt{\#define pl a[p].ch[0]}LCT\text{LCT} 中点 pp 的左儿子。
  • #define pr a[p].ch[1]\texttt{\#define pr a[p].ch[1]}LCT\text{LCT} 中点 pp 的右儿子。

变量

  • Tree a[p]\texttt{Tree a[p]}:存储节点 pp 信息的结构体。
  • int a[p].ch[0/1]\texttt{int a[p].ch[0/1]}:点 pp 的左/右儿子。
  • int a[p].val\texttt{int a[p].val}:单点信息。
  • int a[p].sum\texttt{int a[p].sum}:以 pp 为根的辅助子树的总信息。
  • int a[p].rev\texttt{int a[p].rev}:点 pp 的翻转标记。

函数

  • bool isroot(int p)\texttt{bool isroot(int p)}:判断点 pp 是否是辅助树的根。
  • void pushup(int p)\texttt{void pushup(int p)}:由 pp 的儿子向上传递信息。
  • void pushrev(int p)\texttt{void pushrev(int p)}:翻转以 pp 为根的辅助子树。
  • void pushdown(int p)\texttt{void pushdown(int p)}:下放标记。
  • int get(int p)\texttt{int get(int p)}:得到 pp 在其父亲下的儿子类型。
  • void update(int p)\texttt{void update(int p)}:下放 pp 到其所在辅助树的根的标记。
  • void rotate(int p)\texttt{void rotate(int p)}:旋转 pp 节点。
  • void splay(int p)\texttt{void splay(int p)}:将 pp 旋转到其辅助树的根节点。
  • void access(int p)\texttt{void access(int p)}:将 pp 到原树根的路径改为实链。
  • void makeroot(int p)\texttt{void makeroot(int p)}:将点 pp 改为原树的根。
  • int findroot(int p)\texttt{int findroot(int p)}:找到 pp 所在的原树的根节点。
  • void split(int p,int q)\texttt{void split(int p,int q)}:拿出一颗维护 ppqq 路径的 Splay\text{Splay}
  • void link(int p,int q)\texttt{void link(int p,int q)}:连接 ppqq,不一定保证 ppqq 不连通。
  • void cut(int p,int q)\texttt{void cut(int p,int q)}:断开连接 ppqq 的边,不保证这条边存在。
  • void change(int p,int val)\texttt{void change(int p,int val)}:将点 pp 的单点值修改为 valval

代码

#define pl a[p].ch[0]
#define pr a[p].ch[1]
struct LCT{
	struct Tree{
		int ch[2],fa;
		int val,sum,rev;
	}a[N];
	bool isroot(int p){
		return a[a[p].fa].ch[0]!=p&&a[a[p].fa].ch[1]!=p;
	}
	void pushup(int p){
		a[p].sum=a[pl].sum^a[p].val^a[pr].sum;
	}
	void pushrev(int p){
		swap(pl,pr);a[p].rev^=1;
	}
	void pushdown(int p){
		if(a[p].rev){
			if(pl)pushrev(pl);
			if(pr)pushrev(pr);
			a[p].rev=0;
		}
	}
	int get(int p){
		return a[a[p].fa].ch[1]==p;
	}
	void update(int p){
		if(!isroot(p))update(a[p].fa);
		pushdown(p);
	}
	void rotate(int p){
		int fp=a[p].fa,ffp=a[fp].fa;
		int ty=get(p);
		if(!isroot(fp))a[ffp].ch[get(fp)]=p;a[p].fa=ffp;
		a[fp].ch[ty]=a[p].ch[ty^1];
		if(a[p].ch[ty^1])a[a[p].ch[ty^1]].fa=fp;
		a[p].ch[ty^1]=fp;a[fp].fa=p;
		pushup(fp);pushup(p);
	}
	void splay(int p){
		update(p);
		for(int fp;!isroot(p);rotate(p)){
			fp=a[p].fa;
			if(!isroot(fp))
				rotate(get(fp)^get(p)?p:fp);
		}
		pushup(p);
	}
	void access(int p){
		for(int q=0;p;p=a[q=p].fa)
			splay(p),pr=q,pushup(p);
	}
	void makeroot(int p){
		access(p);splay(p);pushrev(p);
	}
	int findroot(int p){
		access(p);splay(p);
		while(pl)pushdown(p),p=pl;
		splay(p);return p;
	}
	void split(int p,int q){
		makeroot(p);access(q);splay(q);
	}
	void link(int p,int q){
		makeroot(p);if(p!=findroot(q))a[p].fa=q;
	}
	void cut(int p,int q){
		makeroot(p);
		if(findroot(q)==p&&a[q].fa==p&&!a[q].ch[0]){
			a[q].fa=pr=0;
			pushup(p);
		}
	}
	void change(int p,int val){
		splay(p);a[p].val=val;pushup(p);
	}
}lct;
posted @ 2023-08-05 20:27  luckydrawbox  阅读(10)  评论(0)    收藏  举报  来源