跳到主要内容

动态开点线段树指针写法

· 阅读需 2 分钟
//本代码解决的是洛谷上的问题P13825 线段树 1.5
#define ull unsigned long long//宏定义重命名
struct segment_tree//封装在结构体里面
{
segment_tree *ls, *rs;//使用指针,可通过指针查询左右儿子
int l, r;//对应区间
ull sum, add;//和与增量

inline segment_tree( int L,int R ) : l( L ), r( R ), sum( 0 ), add( 0 ){ ls=rs=nullptr; }//构造函数初始化

inline void updata()//懒标记下传
{
if( !ls )//没有儿子就要创造儿子(怎么感觉怪怪的)
{
int mid=( l+r )>>1;
ls=new segment_tree( l,mid );//左儿子申请新空间
rs=new segment_tree( mid+1,r );//右儿子申请新空间
}
if( add )//懒标记下传
{
ls->sum+=add*( ls->r-ls->l+1 );
ls->add+=add;
rs->sum+=add*( rs->r-rs->l+1 );
rs->add+=add;
add=0;
}
}

void change( int L,int R,ull k )//区间修改
{
if( L <= l && r <= R )
{
sum+=k*( r-l+1 );
add+=k;
return ;
}
updata();
int mid=( l+r )>>1;
if( mid >= L ) ls->change( L,R,k );
if( mid < R ) rs->change( L,R,k );
sum=ls->sum+rs->sum;
}

ull query( int L,int R )//区间查询
{
if( L <= l && r <= R ) return sum;
updata();
int mid=( l+r )>>1;
ull res=0;
if( mid >= L ) res+=ls->query( L,R );
if( mid < R ) res+=rs->query( L,R );
return res;
}

};

cin>>n;
auto *root=new segment_tree( 1,n );//设置根
root->change( l,r,k );//指针形式调用
root->query( l,r )<<"\n";//指针形式调用