以下 \(n\le 10^5\)
1 Codeforces 686D
给你一棵树,求出这棵树所有子树的重心。
解
树的重心性质:
- 以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。
- 把两棵树连起来,新树的重心必定在原来两棵树的重心连线的路径上。
在dfs的过程中,我们利用性质1、2,设当前节点为 \(u\) , \(u\) 的其中一个子节点为 \(v\) ,如果 \(v\) 的子树大小超过了 \(u\) 的一半,那么 \(u\) 的子树的重心一定在 \(u\) 和 \(v\) 的子树重心的连线上,我们从 \(v\) 的子树重心暴力往上跳,每次检验是否合法即可。
2 Codeforces 191C
给你一棵树和若干对节点,问对于树的每条边,有多少对节点间的路径经过它。
解
对于每一对点,在这两个点上打上+1标记,在它们的lca上打上-2标记,最后用树上差分查询。
3 Codeforces 842C
定义一个节点的美丽值为从它到根的路径上的所有点的点权的gcd。有若干个询问,询问节点最大可能的美丽值。对于每个询问,你能将树中某一个节点的点权改为0。\(gcd(a,0)=a\)。根节点美丽值为其点权。
点权 \(\le 10^5\) 。
解
我们发现点权不大,于是在dfs下去的过程中,我们维护目前扫过的点的所有因子出现的次数。
设当前节点深度为 \(d\) ,根节点深度为0。
在寻找当前数的因子的过程中,如果有一个因子出现次数 \(≥d\) ,那么这个因子必然就是当前节点的答案之一。
另外,还要考虑不选当前节点的情况。
这样能保证复杂度为 \(O(n\sqrt{n})\) 。
4 Codeforces 813C
有A,B两个人在一棵树上van,A位于1节点,B位于x节点,B先手,每一次A,B可以移动到相邻的节点,也可以不动。当A,B相遇时游戏结束。现在A想要最小化游戏次数,B想要最大化游戏次数。输出最终的游戏次数。
解
找到满足 \(disB[u]<disA[u]\) 且 \(disA[u]\) 最大的节点即可。
5 Codeforces 682C
定义一个节点 \(v\) 是伤心的,如果它的子树中存在一个节点 \(u\) ,使得 \(dis(v,u)>a[u]\) ,其中 \(a[u]\) 为 \(u\) 的点权, \(dis(v,u)\) 为从 \(v\) 到 \(u\) 路径上的边权和。现在你可以进行若干次操作,每次可以删除当前树中的一个叶节点,问最少删除几个节点能使树中没有一个节点是伤心的。
解
对于一个节点 \(u\) ,如果它到根节点的路径上的某一段边权后缀和大于它的点权,那么这个节点必然会使某一个节点伤心,删除这个节点。dp弄一下。
6 Codeforces 337D
有一本魔书在一棵树的一个节点上,这棵树上与它距离不超过 \(d\) 的点会被影响。现在告诉你目前发现已经被影响到的点(可能还有一些点也被影响,但没有告诉你),请你判断魔书有多少种可能的位置。没有输出0。
解
找到距离最远的两个被影响到的点,计算有多少个点到它们的距离 \(\le d\) 。
7 Codeforces 782C
给你一棵树,要给每个节点染色,要求任意相邻的三个节点不能是相同的颜色。问最少使用几种颜色。
解
对于每个节点,颜色从1开始++,如果该颜色使用过就跳过。
8 Codeforces 739B
一棵树,问对于所有的节点,它们各自能控制多少个节点。
节点 \(v\) 能控制节点 \(u\) ,当 \(u\) 在 \(v\) 的子树中,且 \(dis(v,u)>a[u]\) ,其中 \(a[u]\) 为 \(u\) 的点权, \(dis(v,u)\) 为从 \(v\) 到 \(u\) 路径上的边权和。
解
我们发现,对于一个节点 \(u\) ,能控制它的节点必定是它到根节点路径上的点的一个后缀。所以扫到一个节点 \(u\) 时,我们二分一个节点 \(v\) ,使 \(v\) 是深度最小的能控制 \(u\) 的节点,然后用树上差分将从 \(v\) 到 \(u\) 的父亲的所有节点都+1,最后统计每个节点加了几次。
9 Codeforces 980E
一棵树,第 \(i\) 个节点的点权为 \(2^i\) ,现在可以进行 \(k\) 次操作,每次可以删除当前树的一个叶节点,要最大化剩下节点的点权和。问应该删除哪些节点。
解
首先考虑贪心,因为前 \(i-1\) 个节点的点权加起来还没第 \(i\) 个节点的点权大。
我们不妨设根节点为 \(n\) 号节点,然后从大到小枚举其他节点,每次检验当前节点是否能保留。如果当前节点要保留,那么它的所有祖先也要保留。然而,保留的节点个数不能超过 \(n-k\) 个。
怎么统计当前要保留的节点个数?由于保留的节点是单调的,所以用倍增找到第一个未被标记为保留的节点,它到当前节点的距离+1就是需要保留的节点个数。