P2664 树上游戏
首先,将贡献拆成每种颜色对每个点的贡献。
考虑已经选择了一种颜色,将这些颜色的点和所对应边全部删去,就得到了很多连通块。
假设其中一个连通块的大小为 \(siz\),这种颜色对这个连通块内点的贡献就是 \(n-siz\)。
但如果枚举颜色再dfs,时间复杂度为 \(O(n^2)\)。
于是考虑一遍dfs算出所有信息,dfs到一个点的时候只需要计算去掉这个点的颜色且只考虑它子树内与这个点相连的连通块的大小。
这道题加深了我对递归函数的理解,递归之前,只需要考虑目的是什么,递归之后,可以假设已经得到了想要的值,只要对当前值的处理没有问题那么递归函数就没有问题。
P4211 [LNOI2014]LCA
好题。
首先对于每一组询问,问题可以转化为点到根的路径加,查询点到根的路径和,这可以用重链剖分解决。
但不同于一般的重链剖分,这里的区间 \(l\) 到 \(r\) 是孤立的点,也就是说,如果每次都重新维护重链剖分的话,时间复杂度是 \(O(qn\log^2n)\)。
因此考虑怎么同时处理所有询问。
发现对于一个 \((l,r,z)\),可以拆分成 \((1,r,z)-(1,l-1,z)\)。
于是,对询问离线,从左到右依次依次加入每一个点即可。
CF1254D Tree Queries
分类讨论。
-
\(u = v\),所有 \(r\) 都对它有贡献。
-
\(u\) 在 \(v\) 的子树外,对子树外的点有贡献的 \(r\) 为 \(siz[v]\)。
-
\(u\) 在 \(v\) 的子树内,对它有贡献的点为不在子树内的点,如果暴力更新,会被菊花图卡掉。
但观察询问可以发现,本题只需要支持单点查,于是可以考虑每次查一条链,但链又不能暴力跳,自然而然想到了重链剖分。
对于 \(u\) 在 \(v\) 子树内的情况,只需要更新重儿子所在的子树,每次只需要加上轻边连上的父亲对它的贡献即可。
P3703 [SDOI2017]树点涂色
发现操作1很像 LCT 上的 \(access\) 操作。
点到根的路径的颜色树等于经过的虚边数加 \(1\)。
假设当前点为 \(x\),需要把它的右儿子替换为 \(y\),即右儿子的虚边数减 \(1\),\(y\) 的虚边数加 \(1\),这是修改子树信息,可以使用放到 \(dfs\) 序上用线段树维护。
P3714 [BJOI2017]树的难题
点分治。
先将边按照颜色排序加入,对每个分治的根 \(u\),按照颜色顺序依次遍历它的子树。
对于每一棵子树,可以得到一个三元组 \((col,x,val)\),表示结尾的边的颜色,链的长度,权值和。
使用两棵按照链的长度划分的线段树维护,一棵表示异色链,一棵表示同色链。
因为是按颜色遍历的,所以以相同颜色结尾的子树一定是一段连续的区间,先把它们加入第二棵线段树中,遍历完一段相同颜色的区间再取出来放到第一棵线段树中。
P4220 [WC2018]通道
原问题等价于选出一对 \((a,b)\),使得 \(dis_1(a,b)+dis_2(a,b)+dis_3(a,b)\) 最大。
对第一棵树进行边分治,对于一个分治中心的边 \((bg,ed)\),\(a\) 和 \(b\) 一定在异侧,不妨将一侧的点染成黑色,另一侧的点染成白色。
对第二棵树建出虚树,再在这棵虚树上 \(dfs\),对于 \(dfs\) 到的一个点 \(u\),需要在它的左子树和右子树内分别选出一个黑点和白点。
考虑最后答案的式子
\[dis_1(a)+dis_1(b)+w_1(bg,ed)+dep_2(a)+dep_2(b)-2dep_2(u)+dis_3(a,b) \]有这样一个性质,树上有两个点集 \(A\),\(B\),假设 \(a\),\(b\) 属于 \(A\),\(c\),\(d\) 属于 \(B\),\(dis(a,b)\) 为 \(A\) 中的最长距离,\(dis(c,d)\) 为 \(B\) 中的最长距离,那么 \(A\) 和 \(B\) 并集的最长距离一定是从这 \(4\) 个点中选择两个点。
于是,可以考虑将第 \(3\) 棵树的每个点加一个权值,如对于点 \(x\),加上 \(dis_1(x)+dep_2(x)\),求第 \(3\) 棵树中的最长距离时加上起点和终点的权值,在第 \(2\) 棵树上边 \(dfs\) 边合并即可。
标签:03,子树,颜色,剖分,省选,dfs,重链,树上,dis From: https://www.cnblogs.com/yanchengzhi/p/17002021.html