poj3667 Hotel (线段树--区间合并)转自网络【2】
来源:互联网 发布:甲骨文软件招聘骗局 编辑:程序博客网 时间:2024/04/27 17:28
题目大意:有一段长为n的线段,在这条线段上进行操作:1.找出最靠前的长度为l的空线段,并把一个长为l的线段插入在这个地方.2.删除从某点开始长为l的一段线段(有可能并不存在,总之就是把这个区间清空).输出每次插入操作的位置.
一个有 N 个连续房间的旅馆,对 m 次询问对应两种操作。
1 a 询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b 将[a,a+b-1]的房间清空
分析: 区间合并类线段树。
update 成段更新
query 找到满足条件的最左端点
代码转自http://www.notonlysuccess.com/index.php/segment-tree-complete/
注释转自http://blog.csdn.net/h2952220/article/details/7911622
照着大牛的代码打一遍 。。顿时感觉好清爽。。学习中。。
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define lson l,m,rt<<1 //函数用左儿子#define rson m+1,r,rt<<1|1 //函数用右儿子#define havemid int m=(l+r)>>1 //取节点中点#define left (rt<<1) //左儿子#define right (rt<<1|1) //右儿子const int maxn=50005;int lsum[maxn<<2]; //该区间左端开始的空房间数目int rsum[maxn<<2]; //该区间右端开始的空房间数目int msum[maxn<<2]; //该区间里最长的连续空房间的数目int cover[maxn<<2]; //延迟标志 -1表示无需更新,1表示有人入住把空房间数清零,0需要把空房间数堆满void pushdown(int rt,int len){ if(cover[rt]!=-1){ cover[left]=cover[right]=cover[rt];//延迟标志向下传递 msum[left]=lsum[left]=rsum[left]=cover[rt]?0:len-(len>>1);//如果延迟标志为0,则将区间内空房间数清零 msum[right]=lsum[right]=rsum[right]=cover[rt]?0:len>>1;//如果延迟标志为1,则将区间内空房间数堆满 cover[rt]=-1; }}void pushup(int rt,int len){ lsum[rt]=lsum[left];//无论左端开始数的空房间数是否充满整个空间(即即使要加上右儿子从左端开始数的空房间数),都要先把左儿子的房间数复制给父亲的rooml rsum[rt]=rsum[right];//同上 if(lsum[rt]==len-(len>>1))lsum[rt]+=lsum[right];//如果左儿子的rooml充满区间,则加上右儿子的rooml if(rsum[rt]==len>>1)rsum[rt]+=rsum[left];//如果右儿子的roomr充满区间,则加上左儿子的roomr msum[rt]=max(lsum[right]+rsum[left],max(msum[left],msum[right]));//roomr[left] + rooml[right]表示合并区间时产生的连续不断的空房间数}void build(int l,int r,int rt){ msum[rt]=lsum[rt]=rsum[rt]=r-l+1; cover[rt]=-1; if(l==r)return ; havemid; build(lson); build(rson);}void update(int L,int R,int c,int l,int r,int rt){ if(L<=l&&r<=R){ msum[rt]=lsum[rt]=rsum[rt]=c?0:r-l+1;//根据延迟标志选择性更新 cover[rt]=c; return ; } pushdown(rt,r-l+1); havemid; if(L<=m)update(L,R,c,lson);//如果左儿子还有没更新的就更新 if(R>m)update(L,R,c,rson);//同上 pushup(rt,r-l+1);//合并区间}int query(int w,int l,int r,int rt){ if(l==r)return l;//搜到子节点则返回 pushdown(rt,r-l+1);//更新未更新的儿子节点 havemid; if(msum[left]>=w)return query(w,lson);//一直找左儿子的最大连续空房间,一直找到左儿子的roommid不满足,则这个区间一定落在中间的区间,否则在右区间 else if(rsum[left]+lsum[right]>=w)return m - rsum[rt<<1] + 1; else query(w,rson);}int main(){ int n,m,t,a,b; while(scanf("%d%d",&n,&m)!=EOF) { build(1,n,1); while(m--) { scanf("%d",&t); if(t==1){ scanf("%d",&a); if (msum[1]<a)printf("0\n");//如果整个区间都没有连续a的长度 输出0 否则查询时会到奇怪的地方 更新就出错了 else { int res=query(a,1,n,1); printf("%d\n",res); update(res,res+a-1,1,1,n,1); } } else { scanf("%d%d",&a,&b); update(a,a+b-1,0,1,n,1); } } } return 0;}
- poj3667 Hotel (线段树--区间合并)转自网络
- poj3667 Hotel (线段树--区间合并)转自网络【2】
- poj3667 Hotel (线段树区间合并)
- poj3667 Hotel (线段树+区间合并)
- POJ3667:Hotel(线段树区间合并)
- poj3667 Hotel 线段树 区间合并
- POJ3667-Hotel-线段树区间合并(模板)
- poj3667-Hotel 线段树区间合并
- POJ3667--Hotel(区间合并)
- poj3667 Hotel 线段树延迟更新 区间合并
- [线段树]poj3667 Hotel(区间合并、更新、延迟/懒惰标记
- poj3667 线段树(区间合并)
- poj3667(线段树,区间合并)
- poj3667 (线段树区间合并)
- #POJ3667#Hotel(线段树)
- poj3667 Hotel(线段树)
- poj3667线段树区间合并
- poj3667 线段树+区间合并
- Aswing Overview
- haskell(10)
- NDU1332(模拟)
- QUnit源码大致结构分析
- 总结近期算法的学习和感触
- poj3667 Hotel (线段树--区间合并)转自网络【2】
- 产品开发周期如何缩短?
- 线程安全的单例模式
- 常见规则表达式
- GESTURECONFIG 结构与CGestureConfig类
- 阿里巴巴笔试题
- 前端必读:浏览器工作原理
- 去掉(不显示)关闭QQ游戏后跳出的广告
- 去掉html标签的默认样式