How to implement segment tree

本文介绍了一种通用的段树实现模板,该模板使用C++编写,并通过具体示例展示了如何利用此段树进行节点更新及区间求和操作。文章详细解释了段树的结构及其在高效处理区间查询和修改问题上的优势。
    template <typename T>
    class segment_tree
    {
        struct record
        {
            int left;
            int right;
            T value;
            T sum;
        };
        int                 m_size;
        std::vector<record> m_records;

        friend class getter;
    public:
        typedef std::pair<int, int> range;

        class getter
        {
            friend class segment_tree;

            record * m_record, m_reserve;
            std::vector<record*> m_ancestors;
            int m_left, m_right;

            getter( segment_tree & tree, int value_index ) : m_left( 1 ), m_right( tree.m_size )
            {
                assert( value_index >= m_left && value_index <= m_right );
                int my_index = 1;
                m_record = &tree.m_records[ my_index ];
                for ( ;; ) {
                    if ( m_record->left <= 0 ) {
                        m_record->left = m_left;
                        m_record->right = m_right;
                    }

                    if ( m_record->left == value_index && m_record->right == value_index ) {
                        break;
                    }

                    int mid = ( m_left + m_right ) / 2;
                    my_index <<= 1;
                    if ( value_index <= mid ) {
                        m_right = mid;
                    } else {
                        m_left = mid + 1;
                        ++my_index;
                    }
                    m_ancestors.push_back( m_record );
                    m_record = &tree.m_records[ my_index ];
                }
            }

            getter( segment_tree & tree, int left, int right ) : m_left( 1 ), m_right( tree.m_size )
            {
                assert( left >= m_left && right <= m_right && left <= right );
                int my_left = 1, my_right = tree.m_size, my_index = 1;
                record * current = &tree.m_records[ my_index ];
                bool is_left = true;
                T left_sum = 0;
                for ( ; ; ) {
                    if ( current->left <= 0 ) {
                        current->left = my_left;
                        current->right = my_right;
                    }
                    if ( current->left == left && current->right == left ) {
                        break;
                    }

                    int mid = ( my_left + my_right ) / 2;
                    my_index <<= 1;
                    if ( left <= mid ) {
                        my_right = mid;
                        is_left = true;
                    } else {
                        my_left = mid + 1;
                        ++my_index;
                        is_left = false;
                    }
                    if ( !is_left ) {
                        left_sum += tree.m_records[ my_index - 1 ].sum;
                    }
                    current = &tree.m_records[ my_index ];
                }

                my_left = 1, my_right = tree.m_size, my_index = 1;
                current = &tree.m_records[ my_index ];
                is_left = true;
                T right_sum = 0;
                for ( ;; ) {
                    if ( current->left <= 0 ) {
                        current->left = my_left;
                        current->right = my_right;
                    }
                    if ( current->left == right && current->right == right ) {
                        break;
                    }

                    int mid = ( my_left + my_right ) / 2;
                    my_index <<= 1;
                    if ( right <= mid ) {
                        my_right = mid;
                        is_left = true;
                    } else {
                        my_left = mid + 1;
                        ++my_index;
                        is_left = false;
                    }
                    if ( is_left ) {
                        right_sum += tree.m_records[ my_index + 1 ].sum;
                    }
                    current = &tree.m_records[ my_index ];
                }

                m_reserve.left = left;
                m_reserve.right = right;
                m_reserve.sum = tree.m_records[1].sum - (left_sum + right_sum);
                m_reserve.value = m_reserve.sum;

                m_record = &m_reserve;
            }
        public:
            operator T() { return m_record->value; }
            operator const T() const { return m_record->value; }

            getter & operator=( typename boost::call_traits<T>::param_type value )
            {
                T diff = value - m_record->value;
                m_record->value = value;
                m_record->sum = value;
                std::for_each(m_ancestors.begin(), m_ancestors.end(), [diff](record * r) { r->sum += diff; });
                return *this;
            }
        };

        segment_tree( int n ) : m_size( n ), m_records( m_size * 2, record{ -1, -1, 0, 0 } )
        {
            assert(n > 0);
        }

        getter operator[](int i)
        {
            if (i < 0 || i >= m_size) {
                throw std::out_of_range("bad index");
            }
            return getter( *this, i + 1 );
        }
        const getter operator[]( int i ) const
        {
            if ( i < 0 || i >= m_size ) {
                throw std::out_of_range( "bad index" );
            }
            return getter( *this, i + 1 );
        }

        const T operator[]( range r ) const
        {
            if ( r.first < 0 || r.second >= m_size || r.first > r.second ) {
                throw std::out_of_range( "bad index" );
            }
            if (r.first != r.second) {
                return static_cast<const T>( getter( const_cast<segment_tree<T> &>( *this ), r.first + 1, r.second + 1 ) );
            }
            else {
                return static_cast<const T>( getter( const_cast<segment_tree<T> &>(*this), r.first + 1 ) );
            }
        }
    };


We can use the class in this way:

        segment_tree<int> st(10);
        typedef segment_tree<int>::range range;

        st[2] = 10;
        st[0] = 5;
        st[1] = 5;
        verify( st[ 1 ] == 5, stderr, "Failed to get the specified item\n" );
        st[ 3 ] = 15;
        st[8] = 10;
        st[9] = 20;
        st[1] = 10;
        verify( st[ 1 ] == 10, stderr, "Failed to get the specified item\n" );
        st[ 2 ] = 30;
        verify(st[range{1, 2}] == 40, stderr, "Failed to get the sum of the specified range\n");


具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)内容概要:本文介绍了一个涵盖多个科研领域的综合性MATLAB仿真资源集合,重点聚焦于光伏发电系统中基于粒子群优化(PSO)算法的最大功率点追踪(MPPT)技术的Simulink仿真实现。文档还列举了多种MPPT方法(如P&O、增量电导法、神经网络、模糊逻辑控制等),并展示了该团队在电力系统、智能优化算法、机器学习、路径规划、无人机控制、信号处理等多个方向的技术服务能力与代码实现案例。整体内容以科研仿真为核心,提供大量可复现的Matlab/Simulink模型和优化算法应用实例。; 适合人群:具备一定电力电子、自动控制或新能源背景,熟悉MATLAB/Simulink环境,从事科研或工程仿真的研究生、科研人员及技术人员。; 使用场景及目标:①学习并实现光伏系统中基于粒子群算法的MPPT控制策略;②掌握多种智能优化算法在电力系统与自动化领域的建模与仿真方法;③获取可用于论文复现、项目开发和技术攻关的高质量仿真资源。; 阅读建议:建议结合提供的网盘资料,按照研究方向选取对应模块进行实践,重点关注Simulink模型结构与算法代码逻辑的结合,注重从原理到仿真实现的全过程理解,提升科研建模能力。
热成像人物检测数据集 一、基础信息 数据集名称:热成像人物检测数据集 图片数量: 训练集:424张图片 验证集:121张图片 测试集:61张图片 总计:606张热成像图片 分类类别: - 热成像人物:在热成像图像中的人物实例 - 非热成像人物:在非热成像或普通图像中的人物实例,用于对比分析 标注格式: YOLO格式,包含边界框和类别标签,适用于目标检测任务。数据来源于热成像和视觉图像,覆盖多种场景条件。 二、适用场景 热成像监控与安防系统开发: 数据集支持目标检测任务,帮助构建能够在低光、夜间或恶劣环境下自动检测和定位人物的AI模型,提升监控系统的可靠性和实时响应能力。 红外视觉应用研发: 集成至红外摄像头或热成像设备中,实现实时人物检测功能,应用于安防、军事、救援和工业检测等领域。 学术研究与创新: 支持计算机视觉与热成像技术的交叉研究,助力开发新算法用于人物行为分析或环境适应型检测模型。 教育与培训: 可用于高校或培训机构,作为学习热成像人物检测和AI模型开发的教学资源,提升实践技能。 三、数据集优势 精准标注与多样性: 每张图片均由专业标注员标注,确保边界框定位准确,类别分类清晰。包含热成像和非热成像类别,提供对比数据,增强模型的泛化能力和鲁棒性。 场景实用性强: 数据覆盖多种环境条件,如不同光照和天气,模拟真实世界应用,适用于复杂场景下的人物检测任务。 任务适配性高: YOLO标注格式兼容主流深度学习框架(如YOLOv5、YOLOv8等),可直接加载使用,支持快速模型开发和评估。 应用价值突出: 专注于热成像人物检测,在安防、监控和特殊环境检测中具有重要价值,支持早期预警和高效决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值