队伍分好后,我负责数据结构部分。。。。 以后要狂补数据结构了,不能再做水题找存在感了。
今天总结一下线段树 以后长期更新题型。。
**
part 1 线段树是是什么?
**
线段树是一种可以方便维护数列的数据结构。 更新和查找都可以在log(n)的复杂度内完成。 经(我)证(不)明(会)其最差空间复杂度为4*n。记住就好。
线段树可以看做维护线段的树
part 2 线段树如何的结构是什么?
首先,线段树可以看做一颗完全二叉树
完全二叉树有什么用呢? 我们发(百)现(度) 二叉树符合二进制思想,我们可以从一开始从上往下 从左至右编号 如下图
这就很完美,我们可以在log(n)的时间内查找到我们想要查找的任意一个点。
**
part 3 线段树如何建立?
**
下面给出一个看(比)得(较)懂(长)的模板。
线段树的建立 build() 函数
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fuck(x) cout<<x<<endl
#define mem(a,b) memset(a,b,sizeof a)
using namespace std;
const int MAX=55555;
int n;
void pushup(int rt)
{
sum[rt]=(sum[rt<<1|1]+sum[rt<<1|1]); // 递归后把子节点的信息传给父节点
}
void build(int l,int r,int rt)
{
sum[rt]=xxxx;// 初始化节点
// 以下为固定代码
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
区间更新pushdown函数,用于区间更新 add数组为懒惰标记数组
//以下代码为区间加减代码
void pushdown(int rt)
{
if(add[rt]!=-1)
{
sum[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
add[rt<<1]+=add[rt];
add[rt]=-1;
}
}
涉及区间合并 求最长区间或符合条件的连续区间一般这么写
class node
{
public:
int llen,rlen,tlen;
};
// 我们将sum数组由int型换成自定义类
//llen表示该节点所代表区间以左端开始最长合法区间
//rlen为该节点所代表的区间以右端结束的最长合法区间
//tlen为该区间里最长合法区间。
node sum[MAX<<2];
int a[MAX];
void pushup(int l,int r,int rt)
{
int m=(l+r)>>1;
sum[rt].tlen=max(max(sum[rt<<1].tlen,sum[rt<<1|1].tlen),sum[rt<<1|1].llen+sum[rt<<1].rlen);
sum[rt].llen=sum[rt<<1].llen; if(sum[rt].llen==(m-l+1)) sum[rt].llen+=sum[rt<<1|1].llen;
sum[rt].rlen=sum[rt<<1|1].rlen; if(sum[rt].rlen==(r-m)) sum[rt].rlen+=sum[rt<<1].rlen;
}
void build(int l,int r,int rt)
{
sum[rt].llen=sum[rt].rlen=sum[rt].tlen=(r-l+1);
if(l==r) return;
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(l,r,rt);
}
void update(int p,bool flag,int l,int r,int rt)
{
if(l==r)
{
sum[rt].llen=sum[rt].rlen=sum[rt].tlen=flag;
return;
}
int m=(l+r)>>1;
if(p>m) update(p,flag,rson);
else if(p<=m) update(p,flag,lson);
pushup(l,r,rt);
}
int ans=-1;
int query(int p,int l,int r,int rt)
{
if(l==r)
return ans=sum[rt].tlen;
int m=(l+r)>>1;
if(p<=m)
{
if(m-sum[rt<<1].rlen<=p) return query(p,lson)+sum[rt<<1|1].llen;
else return query(p,lson);
}
else
{
if(m+sum[rt<<1|1].llen>=p) return query(p,rson)+sum[rt<<1].rlen;
else return query(p,rson);
}
}
// 网上都有详解