• dsu on tree 小结


    概述

    ( ext{dsu on tree}) 是一种思想,建立在轻重链剖分之上对暴力进行合并的思想。名为树上启发式合并,还是因为它每次保留了重儿子的信息(可以看成是一种合并)。一般用于处理无修改操作的子树问题。

    思路

    • 轻重链剖分出重儿子。
    • 在树上统计答案。(对于当前访问的 (x)
      • (x) 的轻儿子处统计答案,不保留其贡献。
      • (x) 的重儿子处统计答案,并保留其贡献。
      • (x) 的轻儿子的贡献加入。
      • (x) 是某个点的重儿子,保留其贡献,否则不保留其贡献。

    时间复杂度及其证明

    时间复杂度是 (O(n log n(f(n)+g(n)))) 的,其中 (f(n))(g(n)) 分别为统计答案的时间复杂度与加入贡献的时间复杂度。

    证明也很简单。我们知道一个点到根的路径上只会有 (log n) 条轻边。那么,一个点在加入贡献时被它的祖先所访问只会有两种情况:通过一条轻边或通过一条重边。通过轻边会访问 (log n) 次,而通过重边只会访问 (1) 次。故时间复杂度就是 (log) 的。

    trick

    一般可以在树上使用桶来存储一些子树相关的信息,或者使用其他数据结构。思路大体还是和暴力一样,只不过我们希望这个暴力跑的尽可能快(逃

    子树相关的信息可以直接维护,但路径相关的信息因为一定在 ( ext{lca}) 处统计所以我们需要一些技巧。考虑一种处理方式:通过 ( ext{dfs}) 序保证不会出现在非 ( ext{lca}) 处统计答案。

    例题

    CF600E,CF570D,CF208E:使用 ( ext{dsu on tree}),开桶统计信息即可。

    CF375D:开 ( ext{BIT}) 维护信息或直接维护信息,前者 (O(n log^2 n)) 后者 (O(n log n))

    [IOI2011]Race:开 ( ext{map}) 维护从 (1 o x) 的路径长度对应的最小深度,统计答案即可。

    gym102832F:套路的,处理这种 (ioplus j) 的信息,拆位开桶维护即可。

    模板代码

    inline void dfs1(int x,int fa) {
    	sz[x]=1; son[x]=0;
    	for(register int i=h[x];i;i=ver[i]) {
    		int y=to[i]; if(y==fa) continue;
    		dfs1(y,x); sz[x]+=sz[y];
    		if(sz[son[x]]<sz[y]) son[x]=y;
    	}
    }
    inline void upd(int x,int fa,int d) {
    	...
    	for(register int i=h[x];i;i=ver[i]) {
    		int y=to[i]; if(y==fa||y==Son) continue;
    		upd(y,x,d);
    	} 
    	...
    }
    inline void dfs2(int x,int fa,int opt) {
    	for(register int i=h[x];i;i=ver[i]) {
    		int y=to[i]; if(y==fa||y==son[x]) continue;
    		dfs2(y,x,0);
    	}
    	if(son[x]) dfs2(son[x],x,1),Son=son[x];
    	upd(x,fa,1); Son=0;
    	...
    	if(opt==0) upd(x,fa,-1);
    }
    
  • 相关阅读:
    《aelf经济和治理白皮书》重磅发布:为DAPP提供治理高效、价值驱动的生态环境
    在线直播: .NET与物联网主流技术探秘 初识IoT!
    2019,.Net开发者的高光时刻
    git stash 切换分支以后 恢复
    redis之简单动态字符串(SDS)
    mysql机制总结
    mac 修改用户权限
    sql注入方法以及防范
    redis学习
    mysql百万数据分页查询速度
  • 原文地址:https://www.cnblogs.com/tommy0103/p/14419222.html
Copyright © 2020-2023  润新知