poj_3321 线段树/树状数组

题目大意

    一个果树(每个节点的分叉数目不固定)上有N个分叉点(包括最末的叶节点),则有N-1条边,将分叉点进行从1到N编号,每个分叉点上均可以结水果。开始的时候,每个分叉点都有一个水果,之后进行一系列操作,分为两种操作: 
(1)Q x: 查询分叉点x以及x的子树上的水果的总数; 
(2)C x: 更改分叉点x上的结果状态,即原来有水果变为没水果,没水果变为有水果 
    对于给定的每个Q操作,给出结果。

题目分析

    典型的区间操作,但不过是单点更新,区间查询。对于区间操作,可以选用线段树或者树状数组,线段树可以适用于多种类型的区间操作,而树状数组适用于 单点更新,区间查询的操作。 
    线段树的应用范围比树状数组略广,二者均为O(nlog(n))的复杂度,但是树状数组的常数系数要小于线段树,且编程复杂度较低。

一、线段树解法

    对于区间操作,首先需要定出点和区间。本题目中的区间并不很明显&    套用线段树的结构,线段树的叶子节点均为实际存在的节点,而叶子节点的祖先节点是为了加速更改查询操作而设的。因此可以将果树中的N个分支点映射到一个完整的线段树的N个叶节点,然后在这N个叶节点上构建线段树;而其他非叶子节点,均表示某几个连续叶子节点构成的区间;而在对果树上的某个非叶子分叉点及其子树上的水果总数查询的时候,可以将 该分叉点及其子树上所有节点视为一个连续的区间,这个区间并不和线段树中的节点区间对齐,但可以用它们表示---->这样,才查询的时候,就相当于在线段树上进行连续区间的查询操作。 
    对于更新操作,需要从线段树的根节点,一路向下递归查找到叶子节点,沿途经过的所有节点i,节点i代表的区间上的水果总数就要变化1. 
    那么,怎么将果树的各个节点构造出一个连续的区间呢? 可以利用dfs在访问每个果树节点时候的顺序来构造。详见代码。

二、树状数组解法

    dfs时候,果树的每个节点都有一个开始时间和结束时间,这样N个节点,就形成一个2*N的序列A,对于叶子节点,其开始时间点和结束时间点在序列A中是连续的,形成一个长度为2的连续区间,对于非叶子节点,其开始时间和结束时间在序列A中不连续,但它们中间包含的点连续起来形成一个区间,该区间内的点和该节点的子树中的节点完全对应。 
    即序列A中由果树节点x的开始时间点索引start和结束时间点索引end,构成的连续的一个区间和果树中节点x及其子树所有节点完全对应。 
    这样,就可以转化为一个明显的区间,可以更新和查询。

实现(c++)

一、线段树

、树状数组

 

posted @   农民伯伯-Coding  阅读(185)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示