【做题记录】CF1039D You Are Given a Tree
-
\(\text{CF1039D You Are Given a Tree }\)
- 算法:根号分治,\(\text{dp}\)
题目:
有一棵 \(n\) 个节点的树。
其中一个简单路径的集合被称为 \(k\) 合法当且仅当:
树的每个节点至多属于其中一条路径,且每条路径恰好包含 \(k\) 个点。
对于 \(k\in [1,n]\),求出 kk 合法路径集合的最多路径数 即:设 \(k\) 合法路径集合为 \(S\),求最大的 \(|S|\)。
\(n \le 10^5\)。
题解:
首先考虑一个贪心。
在一棵子树中尽可能地最大化完整路径条数。其次最大化未完成的链的长度。
然后进行合并时,先尝试与子树拼接,不行则往上延伸。
不过一次 \(O(n)\)。
设 \(f_k\) 表示对于给定 \(k\) 的答案。
显然有 \(f_k\le \left\lfloor\dfrac{n}{k}\right\rfloor\)
考虑 \(k\) 的取值。
当 \(k\in [1,\sqrt n]\),共 \(\sqrt n\) 种;
当 \(k>\sqrt n\),亦为 \(\sqrt n\);
所以 \(f_k\) 的取值个数为 \(O(\sqrt n)\) 级别的。
然后 \(f\) 显然单调。
所以在边界上二分即可。
伪代码:
f[n]<=f[n-1]<=...<=f[1]
x=f[n];
check(x){
int l=1,r=n;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)<x){
l=mid+1;
res=mid;
}
else r=mid-1;
}
...
}
时间复杂度 \(O(n\sqrt n\log n)\)。