POJ 3667 Hotel (初遇线段树区间合并)
来源:互联网 发布:php 大文件分片上传 编辑:程序博客网 时间:2024/06/13 08:54
题意:
有一个线段,从1到n,下面m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作
1 w 表示在总区间内查询一个长度为w的可用区间并且要最靠左,能找到的话返回这个区间的左端点并占用了这个区间,找不到返回02 a len , 表示从单位a开始,清除一段长度为len的区间(将其变为可用,不被占用),不需要输出。
思路:
这是第一次遇到线段树区间合并的题目,写下感悟,还是对线段的更新和查询工作,但是查询的对象的性质已经不像单点那样,查询的是某个线段的最大可用区间是多少,还要一并查询出最大可用区间最左端的位置,显然不能直接记录最左边的位置,因为父亲和儿子没有递推关系,所以要开其他的线段树记录其他的量,每次查询最起码要在O(1)的时间内算出最大可用区间的最左端位置。
而且也不能光记录最大可用间的长度是多少,因为这样父亲和儿子也构不成递推关系。所以要记录开其他的线段树,这是这类区间合并的共同问题,下面直接说解法方法:
可以开三棵线段树,一个记录此区间的最大可用区间的长度,一个记录此区间从左边开始的可用空间的长度,还有一个记录此区间从右边开始的可用空间的长度。记录这三个量可以互相递推pushup掉三棵线段树上所有的父亲。具体的递推关系可以见代码,但这里必须知道为什么可以递推,因为记录了整个区间从左右端开始延伸的可用空间的长度,递归处理左右儿子,就等价与记录了整个区间上哪些位置可用,哪些位置不可用,就把第一课线段树记录的最大可用空间细节化了,接下来可操作性任意强。
//2720 KB 1063 ms#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define M 50005#define root 1,n,1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;int mmax[M<<2],lmax[M<<2],rmax[M<<2]; //mmax记录整个区间的最大连续空位,lmax记录了这个区间从左边开始的连续空位,rmax记录了这个区间从右边开始的连续空位int col[M<<2]; //lazy tagint n,m;void build(int l,int r,int rt){col[rt]=-1;mmax[rt]=lmax[rt]=rmax[rt]=r-l+1;if(l==r){return;}int m=(l+r)>>1;build(lson);build(rson);}void pushup(int rt,int m){lmax[rt]=lmax[rt<<1];rmax[rt]=rmax[rt<<1|1];if(lmax[rt]==m-(m>>1)) lmax[rt]+=lmax[rt<<1|1];if(rmax[rt]==(m>>1)) rmax[rt]+=rmax[rt<<1];mmax[rt]=max(rmax[rt<<1]+lmax[rt<<1|1],max(mmax[rt<<1],mmax[rt<<1|1]) );//mmax[rt]可能是横跨了左右儿子,也可能是左右儿子中的mmax}void pushdown(int rt,int m){if(col[rt]==-1) return;col[rt<<1]=col[rt<<1|1]=col[rt];mmax[rt<<1]=lmax[rt<<1]=rmax[rt<<1] = col[rt]? 0 :m-(m>>1);mmax[rt<<1|1] = lmax[rt<<1|1] =rmax[rt<<1|1]=col[rt]? 0:(m>>1);col[rt]=-1;}int query(int x,int l,int r,int rt){if(mmax[rt]<x){ //也就是mmax[1]<x只有这一种情况return 0;}if(l==r) return l; //这种情况可能发生x=1的时候pushdown(rt,r-l+1);int m=(l+r)>>1;if(mmax[rt<<1]>=x) return query(x,lson);if(rmax[rt<<1]+lmax[rt<<1|1]>=x) return m-rmax[rt<<1]+1; //直接找到答案if(mmax[rt<<1|1]>=x) return query(x,rson);}void update(int L,int R,int c,int l,int r,int rt){if(L<=l&&r<=R){col[rt]=c;mmax[rt]=lmax[rt]=rmax[rt]= c? 0:(r-l+1);return;}pushdown(rt,r-l+1);int m=(l+r)>>1;if(L<=m) update(L,R,c,lson);if(R>m) update(L,R,c,rson);pushup(rt,r-l+1);}int main(){scanf("%d%d",&n,&m);build(root);while(m--){int op;scanf("%d",&op);if(op==1){int x;scanf("%d",&x);int ans=query(x,root);printf("%d\n",ans);if(ans) update(ans,ans+x-1,1,root);}else {int a,b;scanf("%d%d",&a,&b);update(a,a+b-1,0,root);}}return 0;}
0 0
- POJ 3667 Hotel (初遇线段树区间合并)
- POJ 3667 Hotel 线段树区间合并
- poj 3667 Hotel 线段树区间合并
- POJ 3667 Hotel 线段树 区间合并
- Poj 3667 Hotel 线段树 区间合并
- POJ 3667-hotel(线段树区间合并)
- POJ 3667 Hotel. (线段树 区间合并)
- 【线段树】POJ 3667 Hotel 区间合并
- POJ 3667 Hotel ( 线段树区间合并 )
- 线段树 区间合并 poj 3667 Hotel
- POJ 3667 Hotel 线段树 区间合并
- POJ - 3667 Hotel (线段树 + 区间合并)
- POJ 3667 Hotel 【线段树 区间合并】
- poj 3667 Hotel 【线段树区间合并】
- POJ 3667Hotel 线段树区间合并
- POJ 3667 - Hotel(线段树+区间合并)
- poj 3667 Hotel 线段树区间合并
- poj 3667 hotel (线段树+区间合并)
- HDOJ 1027 Ignatius and the Princess II
- 设计模式_适配器
- 新年快乐,怀恋故乡
- Android Handler,Looper,Message
- 【翻译自mos文章】OUI 的log文件和trace文件的位置
- POJ 3667 Hotel (初遇线段树区间合并)
- 安装11.2.0.3时,OUI的log报错:"OUI-10066:Not All The Dependencies For The Component ... Could Be Found"
- 【翻译自mos文章】在11.2GI的安装过程中,当拷贝到远程节点时OUI 挂起(65%处)
- 【翻译自mos文章】在RHEL7或者OL7上安装11.2.0.4时遇到错误 “undefined reference to symbol ‘B_DestroyKeyObject’”
- 使用runInstaller 的executePrereqs选项来验证os是否符合oracle db software的安装要求
- nike tiempo mpRi MeJ jJSP5
- jghfgfggdfskjghgfgdsafgklhjhgfgdsfajlkhgfd
- CodeForces #292 div.2 题解
- 合家福郭敬明进口国付和鬼地方的发更多的是v银行的费工夫放到大幅度的地方