版权声明:本文为博主原创文章,未经博主允许不得转载。 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);//更改一个值之后 别忘记对整个线段树进行更新。
}
以上就是一个模板(感觉写的比较简陋)可以用来改造一下。
还可以用结构体来做,这种方法不是唯一的,只是我个人比较喜欢。