随笔分类 - 树--------------------------
摘要:【题目】C. Centroids 【题意】给定一棵树,求每个点能否通过 [ 移动一条边使之仍为树 ] 这一操作成为树的重心。n<=4*10^5。 【算法】树的重心 【题解】若树存在双重心,则对于任何一个点将另一边的n/2个点取下来接上去即可,均成立。 若树为单重心,假设w为树的重心及根,x为当前考虑
阅读全文
摘要:【题意】给定n个人的ai和bi,表示第i个人能力值为ai且不能和bi同时选择,求能力值和最大的选择方案。n<=10^6。 【算法】环套树DP(基环树) 【题解】n个点n条边——基环森林(若干环套树子图)。 若原图是树,经典DP做法:f[i][0/1]表示i点选或不选的最大能力值和,则f[i][0]=
阅读全文
摘要:【题意】n个点的树,有m个人同时开始走链,每一步花一秒,n个点都有观察员在ai秒观察,求每个观察员观察到的人数。 【算法】树上差分(主席树||线段树合并) 【题解】一个人的走链可以拆成u-lca和lca-v两部分,可以发现在u-lca链上的点能观察到这个人的w[x],满足所有deep[x]+w[x]
阅读全文
摘要:【题意】n个点的树,m条链,求将一条边的权值置为0使得最大链长最小。 【算法】二分+树上差分 【题解】 最大值最小化问题,先考虑二分最大链长。 对所有链长>mid的链整体+1(树上差分)。 然后扫一遍,对[在所有不满足链上]的边取最大值并check。 具体做法:对于二分的最大链长,将所有链长>mid
阅读全文
摘要:【题意】给定n个点的树,m次求[a,b]和[c,d]中各选出一个点的最大距离。abcd是标号区间,n,m<=10^5 【算法】LCA+树的直径理论+线段树 【题解】 树的直径性质:距离树上任意点最远的点一定是直径的一端。此结论在点集中依然试用。 那么根据性质,容易得到答案路径的两端一定是[a,b]直
阅读全文
摘要:【题意】给定n个点的树,每个点属于一个分类,求每个分类中(至少有2个点)最远的两点距离。n<=200000 【算法】LCA 【题解】结论:树上任意点集中最远的两点一定包含点集中深度最大的点(求树的直径的结论是该结论的特殊情况) 证明:如果有路径不包含深度最大的点,那么用深度最大的点替换在LCA同一侧
阅读全文
摘要:【题意】给定带点权树,要求选择两个点x,y,满足所有点到这两个点中较近者的距离*点权的和最小。n<=50000,h<=100。 【算法】树的重心 【题解】代码参考自:cgh_Andy 观察要求容易发现和重心的定义【所有点距离和最小】十分相似。 要把树分成两部分,于是考虑枚举割掉一条边后,在两棵树中各
阅读全文
摘要:【算法】基环树DP 【题意】给定若干有向基环树,每个点能走的最远路径长度。 【题解】 参考:【BZOJ1589】Trick or Treat on the Farm 基环树裸DP by 空灰冰魂 考虑DAG上DP,令f[x]表示点x开始能到达的最远长度,则f[x]=f[y]+1,x >y。 环套树最
阅读全文
摘要:【算法】可持久化线段树(主席树)+启发式合并+LCA 【题意】给定森林,每次询问u,v路径上的第k小,或给u,v连边(保证森林),n<=8*10^4。 【题解】 区间第k小:离散化,在上一个位置的基础上建可持久化权值线段树,每次比较左子树和k并找到第一个大于等于k的位置。 树上第k小:每个点上其父亲
阅读全文
摘要:【算法】树上贪心 【题解】 因为一个点必须被覆盖,那么它如果没有被子树节点覆盖的话,就覆盖它的父节点。 从叶子开始贪心。 注意,如果它自己已经被选了就不需要选父节点了。 #include<cstdio> #include<algorithm> #include<cstring> #include<c
阅读全文
摘要:【算法】DFS序+树状数组 【题解】题意相当于统计前i-1个点在第i个点的祖先的个数,显然可以用dfs维护,用树状数组差分维护前缀和。 出栈不新加节点就要注意左闭右开,即in[a[i]]处+1,ou[a[i]]+1处-1。 出栈新加节点就要注意数组开双倍。 #include<cstdio> #inc
阅读全文
摘要:【算法】最短路树+(树链剖分+线段树)||最短路树+并查集 【题解】 两种方法的思想是一样的,首先题目限制了最短路树唯一。 那么建出最短路树后,就是询问对于每个点断掉父边后重新找路径的最小值,其它路径只能是这个点和其子树节点通过非树边到达非子树节点。 这样考虑很难统计,换个角度考虑每条非树边的影响。
阅读全文
摘要:【算法】树型DP||树的重心(贪心) 【题解】 两遍DFS,第一次得到所有节点子树的路径和,第二次给出除了该子树外其它部分的路径和,时时计算答案。 long long!!! #include<cstdio> #include<cstring> #include<algorithm> #include
阅读全文
摘要:【算法】最近公共祖先(LCA) 【题解】 点x,y到最近公共祖先z的距离之和相当于x,y到根的距离减去两倍z到根的距离, 即ans=dis[x]+dis[y]-2*dis[z] 记得边数组要开两倍!!!T_T #include<cstdio> #include<algorithm> using na
阅读全文
摘要:【算法】Link-Cut Tree+线段树(维护DFS序) 【题解】整整三天……T_T 这篇题解比较资瓷:permui 这道题虽然树形态没有变化,但用lct写的原因在于把题目中的操作一进行了神转化:每条重链表示一种颜色,点到根的颜色数=经过的轻链数+1。 询问一个点的子树所有结点到根的代价和(的平均
阅读全文
摘要:【算法】树链剖分+线段树(区间加值,区间求和) 【题解】http://hzwer.com/3891.html 中间不要取模不然相减会出错。 血的教训:线段树修改时标记下传+上传,查询时下传。如果修改时标记不下传,下面的结果就会覆盖上面的标记上传造成的影响。 读入后全部排序(离线处理) 链剖之后按顺序
阅读全文
摘要:【算法】树的直径 memset(a,0,sizeof(a)) #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=10010; struct edge{int from,
阅读全文
摘要:【算法】树链剖分+线段树 【题解】线段树的区间加值和区间覆盖操作不能同时存在,只能存在一个。 修改:从根节点跑到目标区域路上的标记全部下传,打完标记再上传回根节点(有变动才需要上传)。 询问:访问到目标区域路上的标记全部下传。 我写的线段树版本是在打标记的同时便对该点的询问项(最大值)做了对应更改,
阅读全文
摘要:【算法】树链剖分+线段树 【题解】 树链剖分算法:http://www.cnblogs.com/onioncyc/p/6207462.html 定义线段树结构体有l,r,lc,rc,sum,data。 lc表示左端颜色,rc表示右端颜色,sum表示颜色种类,data表示区间置为同一个数的标记。 修改
阅读全文
摘要:【算法】树链剖分+线段树 【题解】模板题,见http://www.cnblogs.com/onioncyc/p/6207462.html 调用线段数时要用新编号pos[i] !!! #include<cstdio> #include<cctype> #include<algorithm> using
阅读全文