您的位置:首页 > 其它

POJ 3667 hotel(shǎ崽大神的模板|区间合并)

2012-02-07 11:37 239 查看
继续线段树,这题其实是之前一次练习赛的题目,当时最后两小时苦憋这题。无奈一直TLE,只记得后来婷队讲解时还是一知半解,过了久了就忘记这题了。现在重新翻出来看看,是一道区间合并的题目。

英文一大堆,其实题意很简单:

输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
输入 2 a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间

依然套用了大神的模板代码,真是好用啊。

因为是统计存在的最长连续房间,左右将值分成了三段,计算的时候分三个,即纯左孩子剩余间输中计算和纯右孩子剩余间输中计算,还有一左一右。就三种,有点lazy-tag的感觉,要记得update的时候碰到满足条件也要更新孩子节点。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int maxn=55555;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];   //左右,总的剩余间输
int cover[maxn<<2];         //取值有  -1(初始),0 ,其他值
int max(int a,int b)   //最大值函数
{
return a>b?a:b;
}
void pushdown(int rt,int m)         //更新儿子节点
{
if(cover[rt]!=-1)
{
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=cover[rt]?0:m-(m>>1);
msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=cover[rt]?0:(m>>1);
cover[rt]=-1;
}
}
void pushup(int rt,int m)           //更新根节点
{
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==m-(m>>1))
lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m>>1))
rsum[rt]+=rsum[rt<<1];
msum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1],max(msum[rt<<1],msum[rt<<1|1]));        //根节点值  由下三段中最大值组成。纯左,纯右,一左一右
}
void build(int l,int r,int rt)     //建立
{
msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
cover[rt]=-1;
if(l==r)
return ;
int mid=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt)  //重要的是c的取值 0  还是非0
{
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);
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,c,lson);
if(mid<R)
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);  //lazy-tag
int  mid=(l+r)>>1;
if(msum[rt<<1]>=w)   //纯左孩子
return query(w,lson);
else
if(rsum[rt<<1]+lsum[rt<<1|1]>=w)   //一左一右
return mid-rsum[rt<<1]+1;
return query(w,rson);  //剩下纯右孩子
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
int op,a,b;
scanf("%d",&op);
if(op==1)
{
scanf("%d",&a);
if(msum[1]<a)
puts("0");
else
{
int p=query(a,1,n,1);
printf("%d\n",p);
update(p,p+a-1,1,1,n,1);
}
}
else
{
scanf("%d%d",&a,&b);
update(a,a+b-1,0,1,n,1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: