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; }
相关文章推荐
- 找规律___zxa and set(hdu 5680 BestCoder Round #83)
- C实现复制文件
- 项目感言--功能的模块化
- Notification简单实例
- 机器学习中会用到的矩阵、向量求导公式
- 需求评审五个维度框架分析及其带来的启示-5-结束语
- JS实现星星评分功能实例代码(两种方法)
- js Map
- CUDA中纹理Texture的使用
- CocoaPods+PrefixHeader.pch+Const
- 冒泡排序的Java实现代码
- 需求评审五个维度框架分析及其带来的启示-4-需求条目化管理
- Python日期和时间
- js获取元素下的第一级子元素
- 51nod 1126 求递推序列的第N项
- session URL重写
- BZOJ3511 土地划分 题解&代码
- csdn待改进点之4------>个人资料中的排版格式如此, 这样真的好吗?
- HBase的JavaAPI操作
- 新闻切换特效