您的位置:首页 > 其它

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);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: