您的位置:首页 > 其它

线段树基础详解

2016-07-18 14:53 169 查看
线段树是什么?

线段树(Segment Tree)是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点

以区间[1,6]的线段树为例

对于每一个非叶子节点区间,取mid=(le+ri)/2;将其分为[le,mid],[mid+1,ri]两个子区间。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
#define e tree[id]
#define lson tree[id*2]
#define rson tree[id*2+1]
const int maxn=50005;
int N,M;
struct Tree
{
int le,ri,len;
int maxlen,lelen,rilen;
void init(int a)
{
maxlen=a*len;
lelen=rilen=maxlen;
}
}tree[4*maxn];
void build_tree(int le,int ri,int id)
{
e.le=le; e.ri=ri; e.len=ri-le+1;
e.init(1);  //刚开始都没有被占
if(le==ri)  return;
int mid=(le+ri)/2;
build_tree(le,mid,id*2);
build_tree(mid+1,ri,id*2+1);
return;
}
void pushdown(int id)
{
if(e.maxlen==e.len||e.maxlen==0)  //整个区间要么全空要么全被占
{
int a=(e.maxlen==e.len);
lson.init(a);
rson.init(a);
}
}
void pushup(int id)
{
e.lelen=lson.lelen;
if(e.lelen==lson.len)  e.lelen+=rson.lelen; //可以延伸到右边去
e.rilen=rson.rilen;
if(e.rilen==rson.len)  e.rilen+=lson.rilen; //可以延伸到左边去
e.maxlen=max(lson.maxlen,rson.maxlen);      //更新maxlen的值
e.maxlen=max(e.maxlen,max(e.lelen,e.rilen));
e.maxlen=max(e.maxlen,lson.rilen+rson.lelen);
}
int query(int id,int need)
{
if(e.maxlen<need)  return 0;  //最大区间连续长度都小于need,就是无解
if(e.lelen>=need)  return e.le;    //左边的可行
if(lson.maxlen>=need)  return query(id*2,need);  //左边的最大连续长度大于等于need
if(lson.rilen+rson.lelen>=need)  return lson.ri-lson.rilen+1; //两段中间的部分可行
return query(id*2+1,need);   //查找右边
}
void update(int x,int y,int id,int a)
{
int le=e.le,ri=e.ri;
if(x<=le&&ri<=y){  e.init(a); return; }  //更新
pushdown(id);
int mid=(le+ri)/2;
if(x<=mid)  update(x,y,id*2,a); //左边
if(y>mid)  update(x,y,id*2+1,a);//右边
pushup(id);
}
void solve1()
{
int start;
scanf("%d",&start);
int ans=query(1,start); //找到有连续房间的最左边的下标
printf("%d\n",ans);
if(ans)  update(ans,ans+start-1,1,0); //ans不等于0才更新
}
void solve2()
{
int start,skip;
scanf("%d%d",&start,&skip);
update(start,start+skip-1,1,1);
}
int main()
{
cin>>N>>M;
build_tree(1,N,1);
for(int i=1;i<=M;i++)
{
int type;
scanf("%d",&type);
if(type==1)  solve1();
else  solve2();
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: