首页 > 其他分享 >区间和线段树封装模板

区间和线段树封装模板

时间:2023-04-05 18:45:10浏览次数:29  
标签:arr 封装 线段 数组 长度 维护 SegSumTreest 模板

区间和线段树封装模板,开箱即用
注意:线段树大小最多支持\(2^{30}-1\)个数

声明方法:

  • SegSumTree<typename>st,typename为线段树存储的类型(建议只填写整数类型),建立一颗空线段树,后续必须先用rebuild或resize初始化
  • SegSumTree<typename>st(n) 建立一颗定义了长度的空线段树,n为线段树维护的数组长度
  • SegSumTree<typename>st(n,arr[]) 建立一颗给定了长度和所维护数组的线段树,n为线段树维护的数组长度,arr为线段树维护的数组

功能:

  • update_seg(l,r,v) l到r区间增加v
  • update_poi(k,v) 第k个数单点增加v
  • query_seg(l,r) 返回l到r区间和
  • query_poi(k) 返回第k个数的值
  • empty() 返回一个布尔值,1为非空,0为空
  • size() 返回线段树维护的数组长度,并非线段树数组自身大小
  • clear() 清空线段树,该函数并非只使线段树维护的数清零,而是完全初始化
  • build(n,arr[]) 建立线段树,n为维护的数组长度,arr为数组,使用该函数需保证线段树为空
  • resize(n) 定义线段树大小,n为维护的数组长度,使用该函数需保证线段树为空
template<class T>
class SegSumTree{
    private:
        int n;
        vector<T>sum,add;
        inline void pri_pushup(int pos){
            sum[pos]=sum[pos<<1]+sum[pos<<1|1];
        }
        inline void pri_pushdown(int pos,int l,int r){
            if(add[pos]){
                T len=r-l+1;
                add[pos<<1]+=add[pos];
                sum[pos<<1]+=add[pos]*(len-len/2);
                add[pos<<1|1]+=add[pos];
                sum[pos<<1|1]+=add[pos]*(len/2);
                add[pos]=0;
            }
        }
        void pri_build(int pos,int l,int r,T arr[]){
            if(l==r){
                add[pos]=0;
                sum[pos]=arr[l];
                return;
            }
            int mid=(l+r)/2;
            pri_build(pos<<1,l,mid,arr);
            pri_build(pos<<1|1,mid+1,r,arr);
            pri_pushup(pos);
        }
        void pri_update_seg(int pos,int l,int r,int ll,int rr,T val){
            if(l>rr || r<ll) return;
            if(ll<=l && r<=rr){
                add[pos]+=val;
                sum[pos]+=val*(r-l+1);
                return;
            }
            pri_pushdown(pos,l,r);
            int mid=(l+r)/2;
            if(l<=mid) pri_update_seg(pos<<1,l,mid,ll,rr,val);
            if(mid<r) pri_update_seg(pos<<1|1,mid+1,r,ll,rr,val);
            pri_pushup(pos);
        }
        void pri_update_poi(int pos,int l,int r,int k,T val){
            if(!(l<=k && k<=r)) return;
            if(l==r && l==k){
                sum[pos]+=val;
                return;
            }
            int mid=(l+r)/2;
            if(k<=mid) pri_update_poi(pos<<1,l,mid,k,val);
            else pri_update_poi(pos<<1|1,mid+1,r,k,val);
            pri_pushup(pos);
        }
        T pri_query_seg(int pos,int l,int r,int ll,int rr){
            if(l>rr || r<ll) return 0;
            if(ll<=l && r<=rr){
                return sum[pos];
            }
            pri_pushdown(pos,l,r);
            T res=0;
            int mid=(l+r)/2;
            if(l<=mid) res+=pri_query_seg(pos<<1,l,mid,ll,rr);
            if(mid<r) res+=pri_query_seg(pos<<1|1,mid+1,r,ll,rr);
            return res;
        }
        T pri_query_poi(int pos,int l,int r,int k){
            if(!(l<=k && k<=r)) return 0;
            if(l==r && l==k){
                return sum[pos];
            }
            pri_pushdown(pos,l,r);
            int mid=(l+r)/2;
            if(k<=mid) return pri_query_poi(pos<<1,l,mid,k);
            else return pri_query_poi(pos<<1|1,mid+1,r,k);
        }
    public:
        SegSumTree(){
            n=0;
        }
        SegSumTree(int maxn){
            n=maxn;
            sum.resize(n<<2);
            add.resize(n<<2);
        }
        SegSumTree(int maxn,T arr[]){
            n=maxn;
            sum.resize(n<<2);
            add.resize(n<<2);
            pri_build(1,1,n,arr);
        }
        inline void clear(){
            n=0;
            sum.clear();
            add.clear();
        }
        inline bool empty(){
            return (n==0);
        }
        inline int size(){
            return n;
        }
        inline void resize(int maxn){
            n=maxn;
            sum.resize(n<<2);
            add.resize(n<<2);
        }
        inline void build(int maxn,T arr[]){
            n=maxn;
            sum.resize(n<<2);
            add.resize(n<<2);
            pri_build(1,1,n,arr);
        }
        inline void update_seg(int l,int r,T val){
            pri_update_seg(1,1,n,l,r,val);
        }
        inline void update_poi(int k,T val){
            pri_update_poi(1,1,n,k,val);
        }
        inline T query_seg(int l,int r){
            return pri_query_seg(1,1,n,l,r);
        }
        inline T query_poi(int k){
            return pri_query_poi(1,1,n,k);
        }
};

标签:arr,封装,线段,数组,长度,维护,SegSumTreest,模板
From: https://www.cnblogs.com/SkyNet-PKN/p/17290341.html

相关文章

  • hdu-5306(区间最值+线段树)
    hduGorgeousSequenceHDU-5306题意:给定一个长度为n的区间,做m次操作,三种操作对于序列[L,R]区间中的每个ai,用min(ai,x)替换。打印序列[L,R]区间的最大值打印序列[L,R]区间和因为区间和与区间最值无关,所以无法直接用简单的标记处理。区间最值与区间和如何扯上关系呢?我......
  • shell脚本模板
    shell脚本模板#!/bin/sh./etc/rc.d/init.d/functionsexportLANG=zh_CN.UTF-8#一级菜单menu1(){clearcat<<eof----------------------------------------|#CentOS7.9优化脚本#|----------------------------------------1.一键优化2.自定......
  • 全局异常拦截和返回值封装
    全局异常拦截和返回值封装共分为五个类,分别是错误码枚举类、返回值封装类、自定义业务异常类、全局拦截类、全局返回值处理类。错误码枚举类用来定义返回值的错误码。packagecom.masy.global.exception;/***@ClassNameErrorCode*@Description错误码枚举*@Author......
  • Spring 源码解析 - xml解析封装BeanDefinition(1)
    -  XML解析封装BeanDefinition  断点在 DefaultListableBeanFacy,registerBeanDefinition()二 如果给属性赋值 三 各种postprocessor       ##2、Spring套路点-1、AbstractBeanDefinition看看何时给容器中注入了什么组件-2、BeanFactory让......
  • C++库封装JNI接口——实现java调用c++
    1.JNI原理概述通常为了更加灵活高效地实现计算逻辑,我们一般使用C/C++实现,编译为动态库,并为其设置C接口和C++接口。用C++实现的一个库其实是一个或多个类的简单编译链接产物。然后暴露其实现类构造方法和纯虚接口类。这样就可以通过多态调用到库内部的实现类及其成员方法。进一步......
  • java——maven——idea使用模板(骨架)创建maven工程——webapp(重点)
    黑马模板:                  本地:         ......
  • origin迁移用户主题和模板
    1、用户自定义的文件位于:C:\Users\******\Documents\OriginLab\UserFiles我们拷贝这个文件夹到新的电脑上替换UserFiles文件夹即可2、替换完成后,主题一般会自动更新,但是绘图模板需要手动添加进去。       3、origin的使用套路一般是,先创建模板,然后创建主题,后面......
  • 【230405-2】过定点M(4,2),任意作两条互相垂直的直线l1和l2,分别交xy轴于AB两点,求线段中
    ......
  • KEIL——添加自己的注释模板
    【系列专栏】:博主结合工作实践输出的,解决实际问题的专栏,朋友们看过来!《QT开发实战》《嵌入式通用开发实战》《从0到1学习嵌入式Linux开发》《Android开发实战》《实用硬件方案设计》 长期持续带来更多案例与技术文章分享;欢迎商业项目咨询,10年+软硬全栈内功,助力解决您的尊贵需求。......
  • 函数模板
    一:基本范例 a)模板的定义是以template关键字开头的 b)类型模板参数T前面用typename来修饰,遇到typename就该知道其后面跟的是一个类型。typename可以被class取代 c)类型模板参数T(代表一个类型),前面的修饰符typename/class都用<>括起来 d)T这个名字可以换成任意其他标识符  二:实......