Dsu on tree

dsu on tree学习笔记

\(\uparrow\) 学习参考)

一般来说,Dsu on tree 大多可以和 点分治 互相换着用,都是处理子树或以 \(x\) 为根的路径等问题。

这种问题假设好状态基本上可以秒了。

(当然有时候还可以和 长链剖分 互换)

算法结构与模板

首先类似重链剖分的预处理,求出每个点的 \(dfnl,dfnr,bigson\) 等信息。

对于以 \(x\) 为根的一颗子树,在处理答案时这样做:

  1. 先处理只经过轻儿子的答案,处理完后清空轻儿子的影响。

  2. 处理经过重儿子的答案,不清空影响。

  3. 再次处理 \(x\) 的所有轻儿子,不清空影响并记录答案。

  4. 如果需要清空影响就清空影响。

void solve(int x,int fa,bool Keep)
{
	 for(int i=hea[x];i;i=nex[i])
	 	 if(ver[i]!=fa && ver[i]!=bigson[x])
	 	 	 solve(ver[i],x,false);
			 // 如果需要,这里同时继承轻儿子的答案 
	 if(bigson[x]) solve(bigson[x],x,true);
			 // 如果需要,这里同时继承重儿子的答案 
	 // 只经过 x 的答案
	 for(int i=hea[x];i;i=nex[i])
	 {
	 	 if(ver[i]==fa || ver[i]==bigson[x]) continue;
	 	 for(int j=dfnl[ver[i]];j<=dfnr[ver[i]];j++)
	 	 	 // 统计这棵子树的答案与之前子树的答案 
	 	 for(int j=dfnl[ver[i]];j<=dfnr[ver[i]];j++)
	 	 	 // 将这棵子树的答案加入统计数组 
	 }
	 if(!Keep) // 需要清除影响
	 	 for(int i=dfnl[x];i<=dfnr[x];i++)
		  	 // 全部清除答案,可以相当于 memset,不用担
			 // 心同样状态的其他答案的问题,因为所有答
			 // 案都是先清除再添加的,只有处理完子树答
			 // 案才会处理根的答案。 
}

例题

CF246E Blood Cousins Return

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

CF208E Blood Cousins

P4149 [IOI2011]Race

点分治??当然也可以用 dsu on tree 啦!

posted @ 2022-01-31 08:52  EricQian06  阅读(58)  评论(0编辑  收藏  举报