线段树模板(数组实现)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/83410097

 首先是基本定义环节

因为线段树左子节点和右子节点在构造函数的时候比较常用 我们就把这两个语句简化一下;

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
const int maxn=5008;
int num[maxn<<2];

 之后就是一个更新函数 常用于线段树某处更改数值之后

void pushup(int rt)//更新函数
{
    num[rt] = num[rt << 1] + num[rt << 1 | 1];//求区间和
    num[rt] = max /*min*/ (num[rt << 1] , num[rt << 1 | 1]);//求区间最大最小值
    /* 
      还有很多种不同操作,根据题目要求可以在这里改变,此函数是让整个线段树得以维护的关键
      有了这个函数不断地更新数组的数值,线段树才得以实现
    */
}

接下来便是基本的初始化

void build( int l, int r, int rt)//选择建立的范围(l,r) 选择根节点 rt
{
    num[rt] = 0;
    if( l == r) return;
    int m = (l + r) >> 1;
    build(lson);//用递归的方法
    build(rson);
}

 之后是询问函数 用来求区间内最大值、最小值、区间和或者其他什么奇奇怪怪和区间有关的东西 (不同需求要不同改造)

int qurey( int L, int R, int l, int r, int rt)//这里的例子是求区间内之和 当然求别的可以改造
{
    //(L ,R)代表询问区间 而 (l,r) 代表整个线段树区间 ,rt代表根节点
    if( L <= l && r <= R)// 如果 L ,R  包裹住了 l,r
        return num[rt];
    int m = (l + r) >> 1;
    int ans = 0;
    if(L <= m) ans+=qurey(L, R, lson);
    if(R > m) ans+=qurey(L, R, rson);
    return ans;
}

 之后就是更改某个值了,更改一个值 会对整个线段树都造成影响,要特别注意更新

void updata( int p, /*int add*/,int l, int r, int rt)//更改操作
{
   // p为更改的节点 ,l,r仍然代表区间 rt为根节点 也可以选择对节点更改一些特殊数字
   // 如上方的 add
    if( l == r)
    {
        num[rt]++;
        //num[rt]=add;
        //num[rt]+=add;
		return;
    }
    int m = ( l + r) >> 1;
    if(p <= m) updata(p, lson);
    else updata(p, rson);
    pushup(rt);//更改一个值之后 别忘记对整个线段树进行更新。
}

 以上就是一个模板(感觉写的比较简陋)可以用来改造一下。

还可以用结构体来做,这种方法不是唯一的,只是我个人比较喜欢。

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/83410097