POJ 3667 Hotel (线段树区间合并)
2018-02-05 23:31
375 查看
题意:
一个旅店,有n个房间,接下来会住进一些人,每个人要一段连续的房间,如果有多个,要编号最小的,同时也可能会出去一些人,每次都是出去一个区间的人思路:
区间合并的模板题区间合并其实很简单,以前我们对于父亲更新儿子,会用lazy来减少操作。用儿子更新父亲,也只是一些很简单的相加什么的,区间合并,是因为儿子对父亲产生的影响变得更加复杂,比如这个题目,左右儿子都需要维护的是区间,而在合并的时候,左右儿子接触的地方会产生问题
这个题目我们维护四个值,一个是从左起的连续没有人区间长度lsum,一个是从右起的连续没有人区间长度rsum,一个是区间最长的没人区间msum,当然,还有lazy。
在合并的时候,判断下左右儿子的lsum和rsum是否处于极端情况就可以轻松合并了(极端情况就是全部没人),这样区间合并就变成了正常的线段树了
错误及反思:
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int N = 50010; int lsum[N<<2],rsum[N<<2],msum[N<<2],lazy[N<<2]; int n,k,p,ta,tb; void pushup(int l,int r,int rt) { int m=(l+r)/2; msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),lsum[rt<<1|1]+rsum[rt<<1]); if(lsum[rt<<1]==m-l+1) lsum[rt]=lsum[rt<<1]+lsum[rt<<1|1]; else lsum[rt]=lsum[rt<<1]; if(lsum[rt<<1|1]==r-m) rsum[rt]=rsum[rt<<1|1]+rsum[rt<<1]; else rsum[rt]=rsum[rt<<1|1]; } void pushdown(int l,int b19d r,int rt) { if(lazy[rt]!=-1) { lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; int m=(l+r)/2; if(lazy[rt]){ lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=m-l+1; lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=r-m; } else{ lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=0; lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=0; } lazy[rt]=-1; } } void build(int l,int r,int rt) { if(l==r) { lsum[rt]=rsum[rt]=msum[rt]=1; return ; } int m=(l+r)/2; build(lson); build(rson); pushup(l,r,rt); } void update(int L,int R,int v,int l,int r,int rt) { if(L<=l&&R>=r) { lazy[rt]=v; if(v) lsum[rt]=rsum[rt]=msum[rt]=r-l+1; else lsum[rt]=rsum[rt]=msum[rt]=0; return ; } pushdown(l,r,rt); int m=(l+r)/2; if(L<=m) update(L,R,v,lson); if(R>m) update(L,R,v,rson); pushup(l,r,rt); } int query(int v,int l,int r,int rt) { if(l==r) return l; pushdown(l,r,rt); int m=(l+r)/2; if(msum[rt<<1]>=v) return query(v,lson); else if(rsum[rt<<1]+lsum[rt<<1|1]>=v) return m-rsum[rt<<1]+1; return query(v,rson); } int main() { memset(lazy,-1,sizeof(lazy)); scanf("%d%d",&n,&k); build(1,n,1); while(k--) { scanf("%d",&p); if(p==1) { scanf("%d",&ta); if(msum[1]<ta) printf("0\n"); else{ int ans=query(ta,1,n,1); printf("%d\n",ans); update(ans,ans+ta-1,0,1,n,1); } } else { scanf("%d%d",&ta,&tb); update(ta,ta+tb-1,1,1,n,1); } } }
相关文章推荐
- poj 3667 Hotel(线段树,成段更新,区间合并,Lazy思想)
- poj-3667 Hotel (线段树区间合并)
- POJ 3667 & 1823 Hotel (线段树区间合并)
- Poj 3667 Hotel 线段树 区间合并
- POJ 3667 Hotel(线段树+区间合并)
- POJ - 3667 Hotel (线段树区间合并裸题)
- Poj 3667——hotel——————【线段树区间合并】
- Poj 3667 Hotel 线段树 区间合并
- POJ 3667——Hotel(线段树,区间合并)
- 【POJ 3667】 hotel 【线段树 +区间操作+区间合并】
- POJ 3667 & 1823 Hotel (线段树区间合并)
- POJ-3667 Hotel 线段树区间合并
- poj--3667 Hotel(线段树+区间合并)
- poj 3667 Hotel(线段树,区间合并)
- POJ 3667 Hotel 【线段树 区间合并 + Lazy-tag】
- poj 3667 hotel (线段树+区间合并)
- POJ - 3667 - Hotel (线段树 - 区间合并)
- POJ 3667 Hotel(线段树+区间合并+延迟标记)
- POJ 3667 Hotel 线段树区间合并
- POJ-3667:Hotel(线段树区间合并)