数据结构的半夜----线段树学习笔记1
蒟蒻奉上一篇线段树学习笔记(ssfd)。
曾经有个ACM Au选手尝试往我愚笨的脑袋死命数据结构,最后还是我自己一年脑容量略大之后才真正学进去的。(羞愧)
先借个图
如图所示,线段树有以下性质:
1.线段树本质是棵二叉树.
2.线段树每个节点是代表一个区间l~r,而每个节点的两个儿子是将父节点的区间一分为二,分别l~mid,mid+1~r。
3.叶子节点l等于r
综上所述,我们可以按二叉树的建树方法,若节点编号为th,则节点的左儿子编号为th2,而右儿子记为th2+1。
这里有个小技巧(算不上技巧的技巧)
#define lson th<<1
#define rson th<<1|1
//又是那句话,不是装X,真的会快点的QWQ!!!
现有一个序列A1~N,要将线段树构建以来维护,这里我们用递归建树
#define lson th<<1
#define rson th<<1|1
#define maxn 1000005
int a[maxn];
int tree[maxn*4];//手动画一棵树,发现是会达到4*n的级别的
void build(int l,int r,int th)
{
if(l==r)//当为叶子节点时
{
tree[l]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);//构建左节点
build(mid+1,r,rson);//构建右节点
pushup(th);//从两个子节点更新
}
上述类似于一个建树的模板,根据我们的维护的对象的需要,我们可以将其进行扩展。
如维护最小值和最大值
#define lson th<<1
#define rson th<<1|1
#define maxn 1000005
int a[maxn];
int tree[maxn*4];
int mi[maxn*4];
int ma[maxn*4];
void pushup(int th)
{
mi[th]=min(mi[lson],mi[rson]);
ma[th]=max(ma[lson],ma[rson]);
//从两个儿子进行更新
}
void build(int l,int r,int th)
{
if(l==r)//当为叶子节点时
{
tree[l]=mi[l]=ma[l]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,lson);//构建左节点
build(mid+1,r,rson);//构建右节点
pushup(th);//从两个子节点更新
}
今天晚上就先写到这吧。
23:20
12.7