news 2026/7/10 5:56:43

P2590 树的统计 题目解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
P2590 树的统计 题目解析

一,题面

一棵树上有 n 个节点,编号分别为 1 到 n,每个节点都有一个权值 w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I.CHANGE u t: 把结点 u 的权值改为 t。

II.QMAX u v: 询问从点 u 到点 v 的路径上的节点的最大权值。

III.QSUM u v: 询问从点 u 到点 v 的路径上的节点的权值和。

注意:从点 u 到点 v 的路径上的节点包括 u 和 v 本身。

对于每个QMAX或者QSUM的操作,每行输出一个整数表示要求输出的结果

二,理解

考虑线段树结合树链剖分,按照顺序梳理:

1,输入树,dfs1函数得出基本信息即 fa每个点的父节点 sz每棵子树大小 depth深度 maxson每个点的重孩子(进行重链剖分)

2,dfs2划分重链

(1)得出3个新基本信息即 top每个点所在链的链头 dfn每个点的dfs序 fn每个dfs序所对应的点的编号

(2)分链 重孩子的链头=自己链头 轻孩子单开一条链

3,对dfs序构建线段树 dfs序通用性质把树压成一维数组

同一条重链上所有节点的dfn编号是一段连续区间 可以把树上路径转成线段树区间

任意两点路径能够拆成多段连续区间 所以可以使用线段树维护树上路径

其中pushup,build,普通对于线段树查询的query和update均为模板代码

4,对于链查询的query_chain 求LCA模板代码如下 其中跳链步骤与之相同

int LCA(int x,int y) { while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); x=fa[top[x]]; } if(depth[x]<depth[y]) return x; else return y; }

借助条链,把 x 到 y 的树上路径拆成若干条完整重链 + 最后同链的一段

三,代码

详细解析在注释

#include<bits/stdc++.h> #define ll long long using namespace std; const int N=3e4+5; int a[N],fn[N],fa[N],sz[N],depth[N],dfn[N],top[N],maxson[N],tot,ans,n,q; struct node { int L,R,maxx,sum; } st[N<<2]; vector<int > g[N]; void pushup(int root) { st[root].maxx=max(st[root<<1].maxx,st[root<<1|1].maxx); st[root].sum=st[root<<1].sum+st[root<<1|1].sum; } void build(int root,int L,int R) { st[root].L=L; st[root].R=R; if(L==R) { st[root].maxx=st[root].sum=a[fn[L]];//注意对dfs序打线段树要反映射回编号 return ; } int mid=L+R>>1; build(root<<1,L,mid); build(root<<1|1,mid+1,R); pushup(root); } void update(int root,int L,int R,int k,int val) { if(L==R) { st[root].maxx=st[root].sum=val; return ; } int mid=L+R>>1; if(k<=mid) update(root<<1,L,mid,k,val); else update(root<<1|1,mid+1,R,k,val); pushup(root); } void dfs1(int u,int f) {//作用:求重儿子、sz、depth、fa fa[u]=f,sz[u]=1,depth[u]=depth[f]+1; for(int v:g[u]) { if(v==f) continue; dfs1(v,u); sz[u]+=sz[v]; if(!maxson[u]||sz[maxson[u]]<sz[v]) { //v是否是u的重孩子 maxson[u]=v; } } } void dfs2(int u,int t){//作用划分重链 t即为此时u点对应的链头 top[u]=t; dfn[u]=++tot; fn[tot]=u;//反映射标记dfs序对应的编号 if(maxson[u]){//有重孩子优先走重孩子 dfs2(maxson[u],t);//链头不变,重孩子自动成链 for(int v:g[u]){ if(v!=maxson[u]&&v!=fa[u]){//是轻孩子+不重走 dfs2(v,v);//轻孩子单开链,链头是自己 } } } } int query(int root,int L,int R,int l,int r,int type){ if(type==1){ if(l<=L&&R<=r){ return st[root].maxx; } int mid=L+R>>1; if(r<=mid) return query(root<<1,L,mid,l,r,type); else if(l>mid) return query(root<<1|1,mid+1,R,l,r,type); else return max(query(root<<1,L,mid,l,r,type),query(root<<1|1,mid+1,R,l,r,type)); } else{ if(l<=L&&R<=r){ return st[root].sum; } int mid=L+R>>1; if(r<=mid) return query(root<<1,L,mid,l,r,type); else if(l>mid) return query(root<<1|1,mid+1,R,l,r,type); else return query(root<<1,L,mid,l,r,type)+query(root<<1|1,mid+1,R,l,r,type); } } int query_chain(int x,int y,int type) { if(type==1) ans=-0x3f3f3f3f; else ans=0; while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); int tmp=query(1,1,n,dfn[top[x]],dfn[x],type);//路径的一部分 if(type==1) ans=max(ans,tmp); else ans+=tmp; x=fa[top[x]];//跳到不同的链直到共链 } if(depth[x]<depth[y]) swap(x,y); int tmp=query(1,1,n,dfn[y],dfn[x],type);//对dfs序打线段树,此时跳完后的x和y共链,这是最后的那部分路径 if(type==1) ans=max(ans,tmp); else ans+=tmp; return ans; } int main() { scanf("%d",&n); for(int i=1; i<n; i++){ int aa,bb; scanf("%d%d",&aa,&bb); g[aa].push_back(bb); g[bb].push_back(aa); } for(int i=1;i<=n;i++) scanf("%d",&a[i]); dfs1(1,0); dfs2(1,1);//1的链头是自己 build(1,1,n); scanf("%d",&q); while(q--){ char op[10]; int x,y; scanf("%s%d%d",&op,&x,&y); if(op[0]=='C'){ update(1,1,n,dfn[x],y);//对dfs序打的线段树所以找的是dfn[x] } else{ if(op[1]=='M'){ printf("%d\n",query_chain(x,y,1)); } else{ printf("%d\n",query_chain(x,y,0)); } } } }

好久没干这活了,大肘子欢迎指正

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/10 5:56:16

策略梯度方法

1. Basic idea of policy gradient 2. Metrics to define optimal policies 3. Gradients of the metrics 4. Gradient-ascent algorithm (REINFORCE) 参考文献 本文是一篇学习笔记&#xff0c;内容全部源自于以下视频 https://www.bilibili.com/video/BV1Pz5C6iE3X/?p6&…

作者头像 李华
网站建设 2026/7/10 5:55:32

计算机毕业设计之基于SSM的河南红色旅游景点管理系统

本文介绍了一款使用SSM和Vue开发的河南红色旅游景点管理系统&#xff0c;及其设计与实现过程。根据软件工程对软件系统开发定制的规则和标准&#xff0c;详细的介绍了系统的分析与设计过程&#xff0c;并且详细的概括了系统的开发与测试过程。本文的管理系统使用了java进行系统…

作者头像 李华
网站建设 2026/7/10 5:51:03

反激变换器 CCM/DCM 模式选择 3 大误区解析:以 6.5W NCP1015 设计为例

反激变换器 CCM/DCM 模式选择 3 大误区解析&#xff1a;以 6.5W NCP1015 设计为例 在低功率开关电源设计中&#xff0c;反激变换器凭借其结构简单、成本低廉和电气隔离的优势&#xff0c;成为工程师的首选方案。然而&#xff0c;面对连续导通模式&#xff08;CCM&#xff09;和…

作者头像 李华
网站建设 2026/7/10 5:48:53

【信号分解】基于开普勒优化算法KOA-ICEEMDAN实现信号去躁附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书…

作者头像 李华
网站建设 2026/7/10 5:48:22

MLOps模型部署实战:环境隔离、服务化与可观测性三步落地

1. 项目概述&#xff1a;这不是一份“部署文档”&#xff0c;而是一套可落地的ML工程化操作手册你手头这份标题叫“Deployment ML-OPS Guide Series – 2”&#xff0c;它不是某家云厂商塞给你的PDF说明书&#xff0c;也不是教科书里抽象的CI/CD流水线图。它是我过去三年在三家…

作者头像 李华