把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

题解 CF1059E Split the Tree

洛谷
Codeforces

题意

将一棵 n 个节点的以 1 为根的树拆成若干个链,每条链满足:

  1. 点数不超过 L
  2. 点权和不超过 S
  3. 对于链上的某一位置 ii2),满足 vivi1 的父亲。

求最少分成几个链。特别的,倘若无解,输出 -1。

解决

显然的,我们是从儿子转移到父亲,问题就在于我们父亲节点的选择方式,是再起炉灶,还是承接某一个儿子,又承接哪一个儿子。

想想看,倘若我们将这个树当做一条链,我们应当如何解决。

明显的,我们应该是在能延伸的情况下就尽量延伸,这样我们可以让我们这个新生的节点的末尾更远。

也就是说,当我们在树上时,我们只要有一个儿子能有余地转移,我们就应当承接转移。

接下来的问题在于承接哪一个儿子。

贪心的,我们选择可以延伸更远的那一个儿子的链。

对于处理延伸的长度,我们可以用树上倍增处理,维护 fa 数组与 sum 数组,在处理每个点时,先将自己加上,再从大到小枚举二进制位,倘若满足,立即转移。

总结一下,我们在解决这道题时,我们用倍增维护我们的延伸最远,再在儿子中寻找最远,倘若没有,就从自己再起炉灶。
特殊的,为了判断 -1,我们需要在一开始就判断是否存在一个节点的权值大于 S,倘若存在,那我们的答案就是 -1。

核心代码。

inline void redfs(int now,int fath) {
int u=now,tot=val[now],cnt=0;
for(int i=19; ~i; --i) {
if(cnt+(1<<i)+1>L) continue;
if(tot+sum[u][i]>S) continue;
cnt+=(1<<i);
tot+=sum[u][i];
}
mx[now]=cnt;
for(auto to:lj[now]) {
if(to==fath) continue;
redfs(to,now);
sy[now]=max(sy[now],sy[to]-1);
}
if(sy[now]==-1) {
++ans;
sy[now]=mx[now];
}
}
posted @   djh0314  阅读(5)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示