poj 3667
题意:
输入 n m:有连续n个空房间,接下来有m个操作
输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
输入 2 a b:将[a,a+b-1]的房间清空
思路:
利用线段树建立模型,维护最大连续区间长度,
其中区间长度就是对应的房间数目,
并且对应区间中最左边的端点就是answer,
同时因为需要求出连续区间的最大长度,
因此每次Pushup时都将左右区间合并,
lsum维护该区间从左端点开始的最大长度,rsum维护该区间以右端点结束的最大长度,
msum维护该区间中的最大连续区间长度,cover标志对应区间是否为空(没有住客)
具体实现过程:
Build:建立一颗线段树,其中lsum,rsum,msum初始化为对应区间的长度
query:询问是否有长度为a的连续区间,如果有,返回对应区间的最左边的端点
Updata:更新线段树的信息
Pushup:将左右子区间合并
Pushdown:标志向下传,延迟标志,简单来说就是先标志,
然后等到下次询问或者更新时再去更新线段树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define lson l,mid,x<<1
#define rson mid+1,r,x<<1|1
const int MAX = 55555;
struct node
{
int lsum;
int rsum;
int msum;
int cover;
}tree[MAX<<2];
void Build(int l,int r,int x)
{
tree[x].lsum = tree[x].rsum = tree[x].msum = r - l + 1;
tree[x].cover = -1;
if(l==r) return ;
int mid = (l + r)>>1;
Build(lson);
Build(rson);
}//建树
void Pushup(int x,int m)//更新根节点
{
tree[x].lsum = tree[x<<1].lsum;
tree[x].rsum = tree[x<<1|1].rsum;
if(tree[x].lsum==(m-(m>>1))) tree[x].lsum+=tree[x<<1|1].lsum;
if(tree[x].rsum==(m>>1)) tree[x].rsum+=tree[x<<1].rsum;
tree[x].msum = max(tree[x<<1].rsum + tree[x<<1|1].lsum, max(tree[x<<1].msum,tree[x<<1|1].msum));
}
void Pushdown(int x,int m)
{
if(tree[x].cover!=-1)
{
tree[x<<1].cover = tree[x<<1|1].cover = tree[x].cover;
tree[x<<1].lsum = tree[x<<1].msum = tree[x<<1].rsum = tree[x].cover ? 0 : (m - (m>>1));
tree[x<<1|1].lsum = tree[x<<1|1].msum = tree[x<<1|1].rsum = tree[x].cover ? 0 : (m>>1);//根节点的最大连续区间为左连续区间、右连续区间和挎左右区间三个中最大的一个
tree[x].cover = -1;
}
}
void Update(int A,int B,int C,int l,int r,int x)//订房退房操作(C 的值,1 是定房,0 是退房)
{
if(A<=l && B>=r)
{
tree[x].lsum = tree[x].msum = tree[x].rsum = C ? 0 : (r - l + 1);
tree[x].cover = C;
return ;
}
Pushdown(x,r - l + 1);
int mid = (l + r)>>1;
if(A<=mid) Update(A,B,C,lson);
if(B > mid) Update(A,B,C,rson);
Pushup(x,r - l + 1);
}
int query(int len,int l,int r,int x)//查找是否有满足的连续房间
{
if(l==r) return l;
Pushdown(x,r - l + 1);
int mid = (l + r)>>1;
if(len <= tree[x<<1].msum) return query(len,lson);
else if(len <= tree[x<<1].rsum + tree[x<<1|1].lsum) return mid - tree[x<<1].rsum + 1;
return query(len,rson);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
Build(1,n,1);
while(m--)
{
int k,A,B;
scanf("%d",&k);
if(k==1)
{
scanf("%d",&A);
if(tree[1].msum < A) puts("0");
else
{
int ans = query(A,1,n,1);
printf("%d\n",ans);
Update(ans,ans + A - 1,1,1,n,1);
}
}
else
{
scanf("%d%d",&A,&B);
Update(A,A + B -1,0,1,n,1);
}
}
}
return 0;
}