前言&&思想
一些给定树上一些点集,要处理和该点集有关的询问(例如和点集关系,点集选择限制)的题目,
很多子树没有变化,暴力没有意义。
提取出有关的点和路径,构成虚树
虚树上DP等等,难点往往在于找到非虚树部分的答案。
建立
1.暴力sort再sort
LCA一般都要用,所有点按照dfn序sort,相邻两点的LCA就是所有涉及到的LCA
注意,LCA可能算重!
然后所有的点(包括LCA)再按照dfn sort
利用括号序,用栈模拟,如果新来的点不在栈顶的子树范围内[dfn,dfn2]就弹出栈顶
2.LCT,还支持换根
换根LCA:以r为根,a,b的lca为lca(a,b)⊕lca(a,r)⊕lca(b,r)(伪LCA会被计算两次就消了)
换根dfn序:可以分类讨论子树范围,但是,虚树要sort,你怎么重载小于号?必须有dfn序,,但是不能立刻求出来。
所以,换根大师LCT闪亮登场!
设当前根是rt
access每个点
恰好连到和rt在一条链上就停止,在这个点上打标记
最后找每个点到根路径上第一个有标记的点,就是这个点的父亲。
复杂度还是logn,常数大
例题
保卫王国加强版
对n个点进行限制
把转移变成矩阵
然后倍增维护
和动态DP有相似之处
消耗战
世界树
WC2018 通道
学了边分治再写
Codechef Sad Pairs加强版
• 给出一张图,每个点都有颜色
• 对每个点求出
• 如果把这个点从图中删去
• 那么会有多少对不连通的同色点对
• ????, ???? ≤ 10^7(原题是2e5)
删点不连通,点双,圆方树
非割点:没有影响
割点:子树DP一下
有不同颜色,所以建立虚树(这里sort可能要松式排序,,,)
在圆方树上dfs时候
如果当前点是割点
1.统计当前颜色虚树上的不连通点对,树形DP即可
2.统计所有颜色的虚树上的不连通点对。。。。
一个麻烦事是,虚树上一条边上选择一个原树割点,都会对这个虚树造成相同的影响(两边sz乘积)
n,m 1e7不能带log
所以就树上差分了
设虚树上,(x,y)的边,x是y的父亲
原树上,x的位置减去贡献,y的原树father位置加上贡献
最后dfs扫一遍就行了。
Codechef BTREE
给出一棵树
每次询问给出一个集合,集合中的元素为 ????, ???? ,表示标记了所
有距离 ???? 不超过 ???? 的点,你需要求出一共标记的多少点(一次或
多次)
????, ???? ≤ 10^5
暴力点分治可以在O(logn)时间求出距离x为d的点的个数
CodeChef Union on Tree (虚树+点分治)
建立虚树
然后计算每个点实际能辐射覆盖的最大范围(树形DP一下)(可能来自比较远的辐射中心)
但是显然会算重
考虑对于每个点去重
画图(x,y),x是y的父亲
二分出这个mid,使得y在mid的位置恰好大于等于x在mid的位置的覆盖范围
如果mid位置,两边还能覆盖的范围都是r0,减去距离x为r0的点的个数即可
否则,必然有x覆盖范围比y的多1,大概是这样的图形:
对于中间两个三角形,就是都不能往对面扩展形成的
对于2,就是子树里距离不超过d的点的个数,主席树即可
对于1,距离计算不超过d的点的个数,然后往y走一步(也就是到mid位置),再减去mid子树距离不超过d-1的点的个数
还有一些其他情况:
1.范围不交
2.x或者y的r等于0
3.mid位置是x或者y
结合
动态DP
整体DP