LinkCutTree

FlashHu 巨佬的原理讲解 FlashHu 巨佬的应用讲解

维护链信息

洛谷P3690 【模板】Link Cut Tree 代码+注释
模板,多棵 ( t splay) 实链剖分,以原树中深度为 ( t BST) 关键字,可以动态树连边删边求链权。

HNOI2010 弹飞绵羊 代码
连边删边,通过维护 (sz) 求原树深度,不需要路径操作,所以可以不换根。

国家集训队 Tree II 代码
在普通的 ( t LinkCutTree) 上打懒标记,推标记,( t pushdown) 标记的顺序重要。

动态并查集

洛谷P3950 部落冲突 代码
( t LinkCutTree) 动态维护并查集,不需要 ( t Pushup /qq)

SDOI2008 洞穴勘测 代码
( t LinkCutTree) 动态维护并查集,不需要 ( t Pushup /qq),对,就是重题。

模板

//LinkCutTree
int fa[N],ch[N][2],val[N],re[N],q[N];
int notrt(int u){
	if(!~fa[u]) return 0;
	return ch[fa[u]][0]==u||ch[fa[u]][1]==u;
}
void pushup(int u){
	val[u]=a[u];
	if(~ch[u][0]) val[u]^=val[ch[u][0]];
	if(~ch[u][1]) val[u]^=val[ch[u][1]];
}
void pushre(int u){swap(ch[u][0],ch[u][1]),re[u]^=1;}
void pushdo(int u){
	if(!re[u]) return;
	if(~ch[u][0]) pushre(ch[u][0]);
	if(~ch[u][1]) pushre(ch[u][1]);
	re[u]=0;
}
void rotate(int u){
	int v=fa[u],w=fa[v],d=ch[v][1]==u,s=ch[u][!d];
	if(notrt(v)) ch[w][ch[w][1]==v]=u; ch[u][!d]=v,ch[v][d]=s;
	if(~s) fa[s]=v; fa[v]=u,fa[u]=w,pushup(v);
}
void splay(int u){
	int v=u,w=-1,qc=0; q[qc++]=v;
	while(notrt(v)) q[qc++]=v=fa[v];
	while(qc) pushdo(q[--qc]);
	while(notrt(u)){
		v=fa[u],w=fa[v];
		if(notrt(v)) rotate((ch[v][0]==u)^(ch[w][0]==v)?u:v);
		rotate(u);
	}
	pushup(u);
}
void access(int u){
	for(int s=-1;~u;u=fa[s=u])
		splay(u),ch[u][1]=s,pushup(u);
}
void bert(int u){access(u),splay(u),pushre(u);}
int findrt(int u){
	access(u),splay(u);
	while(~ch[u][0]) pushdo(u),u=ch[u][0];
	return splay(u),u;
}
void lift(int u,int v){bert(u),access(v),splay(v);}
void link(int u,int v){bert(u);if(findrt(v)!=u) fa[u]=v;}
void cut(int u,int v){
	bert(u);
	if(findrt(v)==u&&fa[v]==u&&!~ch[v][0])
		fa[v]=ch[u][1]=-1,pushup(u);
}

P.S.

  • rotate

image.png

原文地址:https://www.cnblogs.com/Wendigo/p/13293363.html