学习笔记第五十三节:LCT

正题

      先放一篇很好的LCT总结:https://www.cnblogs.com/flashhu/p/8324551.html

      看这个就够了,讲得非常好,在这里我就不多说了。

      说几个要点,学会可以帮助更好的理解LCT:

      1.若给出的是一棵有根树,那么就不能makeroot这种操作。

      2.其次,若要找两个点的lca,我们可以access(x),再access(y),然后找x所在splay的父亲即可。特判在一条链上的情况

      3.实际上LCT能维护的不过也就是子树信息,路径信息,子树信息可以看做是把一个点splay后去除左儿子的信息

      4.路径信息就直接split(x,y),如果不支持换根或者不支持改变边的状态,考虑树上差分。

      在今后刷LCT的时候遇到有趣的事情或者解法,会补blog。

      体表粘一下xzy神的。(貌似前面一大片题都可以用树剖搞定,不过显然LCT代码又短,跑起来又快)

  1. P2147 [SDOI2008]Cave 洞穴勘测
  2. P3690 【模板】Link Cut Tree
  3. P3203 [HNOI2010]弹飞绵羊
  4. P2173 [ZJOI2012]网络
  5. P1501 [国家集训队]Tree II
  6. P4172 [WC2006]水管局长
  7. [Luogu/POJ3522]最小差值生成树
  8. P2387 [NOI2014]魔法森林
  9. [HDU5398] GCD Tree
  10. [BZOJ4736]温暖会指引我们前行
  11. P1505 [国家集训队]旅游
  12. P2542 [AHOI2005]航线规划
  13. P2486 [SDOI2011]染色
  14. P4180 [Beijing2010组队]次小生成树Tree
  15. [BZOJ4998]星球联盟
  16. [BZOJ2959]长跑
  17. [BJOI2014]大融合
  18. [UOJ207]共价大爷游长沙
  19. [COGS2701]动态树
  20. [BZOJ3626][LNOI2014]LCA
  21. [THUWC 2017]在美妙的数学王国中畅游
  22. [AH2017/HNOI2017]单旋
  23. [BZOJ3514]Codechef MARCH14 GERALD07加强版
  24. [SDOI2017]树点涂色
  25. [luogu3613]睡觉困难综合征
  26. [ZJOI2016]大森林
  27. [ZJOI2018]历史
  28. Qtree1
  29. Qtree2
  30. Qtree3
  31. Qtree4
  32. Qtree5
  33. Qtree6
  34. Qtree7

      最后粘一粘模板:

#include
#define ls son[x][0]
#define rs son[x][1]
using namespace std;

const int N=100010;
int sum[N],val[N],son[N][2],fa[N],n,m,type,x,y;
int sta[N],top=0;
bool rev[N];

bool isroot(int x){
	return son[fa[x]][0]!=x && son[fa[x]][1]!=x;
}

void pushdown(int x){
	if(!rev[x]) return ;
	rev[x]=false;
	rev[ls]^=true;rev[rs]^=true;
	swap(son[ls][0],son[ls][1]);
	swap(son[rs][0],son[rs][1]);
}

void update(int x){
	sum[x]=sum[ls]^sum[rs]^val[x];
}

void rotate(int x){
	int f=fa[x],ff=fa[f],w=0;
	if(son[f][0]==x) w=1;
	else w=0;
	if(!isroot(f)){
		if(son[ff][0]==f) son[ff][0]=x;
		else son[ff][1]=x;
	}fa[x]=ff;
	son[f][1-w]=son[x][w];
	if(son[x][w]) fa[son[x][w]]=f;
	fa[f]=x;son[x][w]=f;
	update(f);update(x);
}

void splay(int x){
	sta[top=1]=x;for(int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
	for(int i=top;i>=1;i--) pushdown(sta[i]);
	while(!isroot(x)){
		if(!isroot(fa[x])){
			if((son[fa[x]][0]==x) ^ (son[fa[fa[x]]][0]==fa[x])) rotate(x);
			else rotate(fa[x]);
		}
		rotate(x);
	}
}

void access(int x){
	for(int last=0;x;last=x,x=fa[x]) splay(x),son[x][1]=last,update(x);
}

void makeroot(int x){
	access(x);splay(x);rev[x]^=1;swap(son[x][0],son[x][1]);
}

int findroot(int x){
	access(x);splay(x);
	while(son[x][0]) pushdown(x),x=son[x][0];
	return x;
}

void split(int x,int y){
	makeroot(x);access(y);splay(y);
}

void link(int x,int y){
	split(x,y);
	if(findroot(y)==x) return ;
	fa[x]=y;
}

void solve(int x,int y){
	split(x,y);
	printf("%d\n",sum[y]);
}

void cut(int x,int y){
	split(x,y);
	if(findroot(y)!=x || fa[x]!=y || son[x][1]) return ;
	fa[x]=son[y][0]=0;
	update(y);
}

void change(int x,int y){
	access(x);splay(x);val[x]=y;update(x);
}

int main(){
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&val[i]),sum[i]=val[i];
	while(m--){
		scanf("%d %d %d",&type,&x,&y);
		if(type==0) solve(x,y);
		if(type==1) link(x,y);
		if(type==2) cut(x,y);
		if(type==3) change(x,y);
	}
}

 

你可能感兴趣的:(学习笔记)