线段树基础详解
2016-07-18 14:53
169 查看
线段树是什么?
线段树(Segment Tree)是一种二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
以区间[1,6]的线段树为例
对于每一个非叶子节点区间,取mid=(le+ri)/2;将其分为[le,mid],[mid+1,ri]两个子区间。
View Code
线段树(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
相关文章推荐
- shell中感叹号与引号用法
- RadioButton 多行 多列显示
- HDU 1166 敌兵布阵 (树状数组 || 线段树)
- Java中获取明天或者昨天的日期的方法
- OpenCV 颜色空间转换参数CV_BGR2GRAY改变
- 设计模式之状态模式
- 对浏览器版本的判断
- hdu5720Wool+区间覆盖总长
- 从FineReport看开放式引擎API
- java学习之container
- JSP的隐含对象
- DB2 初试还原联机备份
- 【开源】Time-NLP 中文语句中的时间语义识别
- items,iteritems
- Error: Error parsing F:\android-sdk_r24.3.4-windows\android-sdk-windows\system-images\android-23\and
- android seekbar 注意事项
- 命令行运行java程序*.jar包
- db2 aix 定时 备份
- bzoj 2324(最小费用最大流)
- 移动支付——支付宝