您的位置:首页 > 其它

POJ 3667 Hotel

2016-06-09 10:32 281 查看

题目大意

我用自己的话概括一下,给一段长为n的空区间,有2种操作,一种就是找到最左边长为w的连续的空区间并返回这段空区间最左边的区间号。另一种就是将从区间号a开头长度为b的这一段区间清空。

题目分析

这道题是关于线段树区间合并的基础题,不过自己想了很久,自己也写了十几篇的线段树的博客有了自己线段树的风格,其实个人感觉挺简约的,看着也挺舒服,感觉封装在结构体中挺丑的,什么都要加个前缀。

合并的时候需要处理的点挺多的,这里我就不一一列举了,详细的看我的代码。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define mid (L+R)/2
#define lson o<<1, L, mid
#define rson o<<1|1, mid+1, R
const int maxn = 50005;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2];
int cover[maxn<<2]; // 延迟标记

void pushdown(int o,int m) //标记往下
{
if(cover[o] != -1) //等于1表示这些房子住了,等于0表示住的人走了
{
cover[o<<1] = cover[o<<1|1] = cover[o];
msum[o<<1] = lsum[o<<1] = rsum[o<<1] = cover[o]? 0 : m - (m >> 1);
msum[o<<1|1] = lsum[o<<1|1] = rsum[o<<1|1] = cover[o] ? 0 : (m >> 1);
cover[o] = -1;
}
}

void pushup(int o,int m)  //这里大家可以仔细想一下,很容易理解
{
lsum[o] = lsum[o<<1];
rsum[o] = rsum[o<<1|1];
if(lsum[o] == m-(m>>1)) lsum[o] += lsum[o<<1|1];
if(rsum[o] == (m>>1))  rsum[o] += rsum[o<<1];
msum[o] = max(rsum[o<<1]+lsum[o<<1|1], max(msum[o<<1], msum[o<<1|1]));
}

void build(int o,int L,int R)
{
msum[o] = rsum[o] = lsum[o] = (R-L+1);
cover[o] = -1;
if(L == R) return ;
build(lson);
build(rson);
}

void update(int o,int L,int R,int l,int r,int c)
{
if(l <= L && R <= r){
msum[o] = lsum[o] = rsum[o] = c?0:R-L+1;
cover[o] = c;
return ;
}
pushdown(o, R-L+1);   //标记向下推移
if(l <= mid) update(lson, l, r, c);
if(mid < r) update(rson, l, r, c);
pushup(o, R-L+1); //同时更新父亲结点的信息
}

int query(int o,int L,int R,int w) //返回最左边的能容纳长为w的区间的左端点,注意是找最左边
{
if(L == R) return L;  //这一点不能掉了
pushdown(o, R-L+1);
if(msum[o<<1] >= w) return query(lson,w); //左区间有就到左孩子区间
else if(rsum[o<<1] + lsum[o<<1|1] >= w) //处于左区间与右区间的中间
return mid - rsum[o<<1] + 1;
else
return query(rson,w);  //只能找右区间了
}

int main()
{
int n,m;
scanf("%d%d", &n, &m);
build(1, 1, n);
while(m--){
int op,a,b;
scanf("%d", &op);
if(op == 1)
{
scanf("%d", &a);
if(msum[1] < a)  //如果根没有,那么一定没有
printf("0\n");
else{
int p = query(1, 1, n, a);
printf("%d\n", p);
update(1, 1, n, p, p+a-1, 1);
}
}
else
{
scanf("%d%d", &a, &b);
update(1, 1, n, a, a+b-1, 0);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: