news 2026/8/20 10:24:06

P1612 树上的链 【洛谷算法习题】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P1612 树上的链 【洛谷算法习题】

P1612 树上的链

网页链接

P1612 树上的链

题目描述

给定一棵有n nn个节点的树。每个节点有一个点权和一个参数。节点i ii的权值为w i w_iwi,参数为c i c_ici1 11是这棵树的根。

现在,对每个节点u uu1 ≤ u ≤ n 1 \leq u \leq n1un),请在树上你找到最长的一条链v 1 , v 2 , … v m v_1, v_2, \dots v_mv1,v2,vm,满足如下条件:

  1. v 1 = u v_1 = uv1=u
  2. 2 ≤ i ≤ m 2 \leq i \leq m2im, 有v i v_iviv i − 1 v_{i - 1}vi1的父节点。
  3. 链上节点的点权和不超过c u c_ucu,即∑ j = 1 m w v j ≤ c u \sum_{j = 1}^m w_{v_j} \leq c_uj=1mwvjcu

输入格式

第一行是一个整数,表示树的节点数n nn
第二行有n − 1 n - 1n1个整数p 2 , p 3 , … p n p_2, p_3, \dots p_np2,p3,pn,其中p i p_ipi表示节点i ii的父节点。
第三行有n nn个整数,第i ii个整数表示节点i ii的权值w i w_iwi
第四行有n nn个整数,第i ii个整数表示节点i ii的参数c i c_ici

输出格式

输出一行n nn个用空格隔开的整数,第i ii个整数表示节点i ii对应的链的最长长度。

输入输出样例 #1

输入 #1

5 1 1 2 2 1 2 3 4 5 1 3 3 6 8

输出 #1

1 2 1 2 3

说明/提示

数据规模与约定

对全部的测试点,保证1 ≤ u , v ≤ n ≤ 10 5 1 \leq u, v \leq n \leq 10^51u,vn1051 ≤ p i < i 1 \leq p_i \lt i1pi<i1 ≤ w i ≤ c i ≤ 10 9 1 \leq w_i \leq c_i \leq 10^91wici109

解题思路

本题是树上祖先链后缀和 + 二分查找的经典题型。对于每个节点u uu,要求出从u uu出发沿父边向上延伸的一条最长链,使得链上节点权值之和不超过c u c_ucu。利用树的前序遍历性质与权值非负带来的前缀和单调性,可以在 DFS 过程中维护根到当前节点的前缀和栈,并通过二分快速定位最远合法祖先,从而O ( n log ⁡ n ) O(n\log n)O(nlogn)求出所有答案。

1. 问题等价转化
  • 链的限制:所求链必须从u uu开始,不断走向父节点,因此它一定是根到u uu的路径上的一段后缀
  • 权值和约束:设根到u uu路径上各节点权值和为sum ( u ) \text{sum}(u)sum(u),若链起点为v vv(祖先),终点为u uu,则该链权值和为sum ( u ) − sum ( parent ( v ) ) \text{sum}(u)-\text{sum}(\text{parent}(v))sum(u)sum(parent(v))。需要满足不超过c u c_ucu
  • 单调性:由于w i ≥ 1 w_i \ge 1wi1,从根到任意节点的前缀和严格递增。因此sum ( u ) \text{sum}(u)sum(u)已知,要找最远的v vv,相当于找最小的祖先前缀和S SS,使得sum ( u ) − S ≤ c u \text{sum}(u)-S \le c_usum(u)Scu,即S ≥ sum ( u ) − c u S \ge \text{sum}(u)-c_uSsum(u)cu。前缀和递增,可用二分查找左边界。
  • 答案长度:若二分找到的最小前缀和位于栈中下标ret,则链起点为下标ret+1对应的节点,链长度为当前栈内节点数减去ret,即stk.size() - ret - 1
2. 算法实现:DFS 维护前缀和栈 + 二分
  1. 建树:根据输入的父节点数组p 2 … p n p_2 \dots p_np2pn构建邻接表。
  2. 初始化前缀和栈stk初始放入0 00,表示根节点父亲的前缀和为0 00
  3. DFS 遍历
    • 进入节点u uu时,将stk.back() + w[u]压入栈,得到当前根到u uu的前缀和。
    • stk上二分查找最小的下标ret,满足stk.back() - stk[ret] <= c[u]
    • 节点u uu的答案ans[u] = stk.size() - ret - 1
    • 递归访问所有子节点。
    • 回溯时弹出栈顶,恢复祖先链状态。
  4. 输出答案:按节点编号顺序输出ans[i]
3. 复杂度分析
  • 时间复杂度:每个节点入栈、出栈一次,并执行一次二分查找,复杂度O ( log ⁡ n ) O(\log n)O(logn)。总时间复杂度O ( n log ⁡ n ) O(n \log n)O(nlogn)n ≤ 10 5 n \le 10^5n105完全可行。
  • 空间复杂度:邻接表、权值与答案数组均为O ( n ) O(n)O(n),前缀和栈深度为树高,最坏O ( n ) O(n)O(n)

总结

核心思想是将树上向上延伸的链转化为根到当前节点前缀和的一段后缀。利用前缀和单调递增,对每个节点二分出满足限制的最远祖先,即可得到最长合法链长度。DFS 中的前缀和栈自然维护了祖先路径,回溯时弹出恢复,保证每个节点查询的都是其自身到根的链信息。

代码简要说明

  1. 全局数组
    • e[maxn]:邻接表,存储每个节点的子节点。
    • w[], c[], p[], ans[]:分别表示权值、参数、父节点、答案。
    • stkvector<ll>,用于记录当前 DFS 路径上的前缀和。
  2. DFS 函数dfs(u)
    • 将当前节点权值加到栈顶前缀和上并压栈。
    • 二分查找满足stk.back() - stk[mid] <= c[u]的最小mid,记为ret
    • 计算ans[u] = stk.size() - ret - 1
    • 遍历子节点递归调用。
    • 回溯时stk.pop_back()恢复状态。
  3. 主函数
    • 读入n nn,构建树。
    • 读入权值数组和参数数组。
    • 初始化stk{0},从根节点1 11开始 DFS。
    • 顺序输出所有答案。

代码内容

#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'typedeflonglongll;typedefunsignedlonglongull;typedefvector<vector<ll>>vvt;typedefpair<ll,ll>pll;constll N=1e3+10;constll INF=1e18;constll M=1e6+10;constll mod=1e9+7;constll maxn=100005;array<vector<ll>,maxn>e;array<ll,maxn>w,c,p,ans;vector<ll>stk;voiddfs(ll u){stk.push_back(w[u]+stk.back());ll ret=0;ll l=0,r=(ll)stk.size()-1,mid;while(l<=r){mid=(l+r)>>1;if(stk.back()-stk[mid]<=c[u]){ret=mid;r=mid-1;}elsel=mid+1;}ans[u]=(ll)stk.size()-ret-1;for(autov:e[u])dfs(v);stk.pop_back();}intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);ll n;cin>>n;for(ll i=2;i<=n;i++){cin>>p[i];e[p[i]].push_back(i);}for(ll i=1;i<=n;i++)cin>>w[i];for(ll i=1;i<=n;i++)cin>>c[i];stk.push_back(0);dfs(1);for(ll i=1;i<=n;i++){cout<<ans[i];if(i==n)cout<<endl;elsecout<<' ';}return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/20 10:23:50

量化研究数据库选型指南:从CSV到专业方案实战对比

在实际量化研究项目中&#xff0c;数据存储方案的选择往往比策略模型本身更早地决定了一个项目的天花板。很多个人研究者在初期会习惯性地使用 CSV 或 Excel 文件&#xff0c;但随着数据量增长、因子维度增加以及回测频率提升&#xff0c;文件读写慢、内存溢出、数据一致性差等…

作者头像 李华
网站建设 2026/8/20 10:22:50

Git与GitHub实战指南:从版本控制到团队协作的完整入门

这次我们来看一个对开发者来说几乎每天都会接触&#xff0c;但很多新手可能知其然不知其所以然的话题&#xff1a;Git 和 GitHub。在“vibecoding时代”&#xff0c;这两个工具早已不是高级开发者的专属&#xff0c;而是所有与代码、文档、协作相关工作的基础设施。无论你是刚入…

作者头像 李华
网站建设 2026/8/20 10:22:46

小红书作品下载实操指南:用 XHS-Downloader 三步备份原图与高清视频

小红书作品下载实操指南&#xff1a;用 XHS-Downloader 三步备份原图与高清视频 【免费下载链接】XHS-Downloader 小红书&#xff08;XiaoHongShu、RedNote&#xff09;链接提取/作品采集工具&#xff1a;提取账号发布、收藏、点赞、专辑作品链接&#xff1b;提取搜索结果作品、…

作者头像 李华
网站建设 2026/8/20 10:19:57

书接上回(二)

#pycharm里边的注释就是#&#xff0c;多行一起注释呢就是全部选中然后control/即可 一、YOLO的自定义数据集 1.字符串的split&#xff08;&#xff09;用法&#xff1a;去除字符串开头和结尾的空字符串 空格&#xff08;你按空格键打出来的 " "&#xff09; 换行…

作者头像 李华
网站建设 2026/8/20 10:17:06

猫抓Cat-Catch浏览器媒体嗅探扩展的底层原理与架构深度解析

猫抓Cat-Catch浏览器媒体嗅探扩展的底层原理与架构深度解析 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 某个深夜&#xff0c;你想把一集综艺下…

作者头像 李华
网站建设 2026/8/20 10:16:34

日本11家车企联手建加氢站:氢能基础设施的破局之道

1. 为什么日本车企要抱团搞加氢站&#xff1f; 最近看到丰田牵头&#xff0c;联合了本田、日产、铃木、斯巴鲁、五十铃、大发、马自达、三菱扶桑、日野、三菱商事&#xff0c;一共11家公司&#xff0c;宣布要成立一家合资企业&#xff0c;专门在日本国内加速部署氢气站。这个新…

作者头像 李华