题目链接:http://poj.org/problem?id=3667

最初给你n间空房,m个操作:

  操作1 a 表示检查是否有连续的a间空房,输出最左边的空房编号,并入住a间房间。

  操作2 a b 表示将编号为a之后的b间房间清空。

典型的区间合并问题,这位大牛讲的更清楚:http://www.cnblogs.com/yewei/archive/2012/05/05/2484471.html

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 5e4 + ;
//sum表示这个区间的最大数,lsum表示从这个区间最左边开始连续的最大数,rsum与lsum方向相反
struct data {
int l , r , lsum , rsum , sum , cover;
}T[MAXN << ]; void build(int p , int l , int r) {
int mid = (l + r) >> ;
T[p].lsum = T[p].rsum = T[p].sum = r - l + ;
T[p].cover = -;
T[p].l = l , T[p].r = r;
if(l == r)
return ;
build(p << , l , mid);
build((p << )| , mid + , r);
} void Pushdown(int p) {
if(T[p].cover != -) {
int ls = p << , rs = (p << )|;
T[ls].cover = T[rs].cover = T[p].cover;
T[ls].lsum = T[ls].rsum = T[ls].sum = T[p].cover ? : T[ls].r - T[ls].l + ;
T[rs].lsum = T[rs].rsum = T[rs].sum = T[p].cover ? : T[rs].r - T[rs].l + ;
T[p].cover = -;
}
} void Pushup(int p) {
T[p].lsum = T[p << ].lsum;
T[p].rsum = T[(p << )|].rsum;
if(T[p].lsum == T[p << ].r - T[p << ].l + )
T[p].lsum += T[(p << )|].lsum;
if(T[p].rsum == T[(p << )|].r - T[(p << )|].l + )
T[p].rsum += T[p << ].rsum;
int temp = max(T[(p << )|].sum , T[p << ].rsum + T[(p << )|].lsum);
T[p].sum = max(T[p << ].sum , temp);
} int query(int p , int len) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == T[p].r) {
return T[p].l;
}
Pushdown(p);
if(T[p << ].sum >= len) { //左孩子区间的最大数,优先选左孩子
return query(p << , len);
}
else if(T[p << ].rsum + T[(p << )|].lsum >= len) { //其次要是左孩子的rsum和右孩子的lsum 加起来大于len
return mid - T[p << ].rsum + ;
}
else {
return query((p << )| , len); //最后就是右孩子
}
} void updata(int p , int l , int r , int flag) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
T[p].sum = T[p].lsum = T[p].rsum = flag ? : r - l + ;
T[p].cover = flag;
return ;
}
Pushdown(p);
if(r <= mid) {
updata(p << , l , r , flag);
}
else if(l > mid) {
updata((p << )| , l , r , flag);
}
else {
updata(p << , l , mid , flag);
updata((p << )| , mid + , r , flag);
}
Pushup(p);
} int main()
{
int n , m , choose , u , v;
while(~scanf("%d %d" , &n , &m)) {
build( , , n);
while(m--) {
scanf("%d" , &choose);
if(choose == ) {
scanf("%d" , &u);
if(T[].sum < u)
printf("0\n");
else {
int pos = query( , u);
printf("%d\n" , pos);
updata( , pos , pos + u - , );
}
}
else {
scanf("%d %d" , &u , &v);
updata( , u , min(u + v - , n) , );
}
}
}
return ;
}

POJ 3667 Hotel (线段树区间合并)的更多相关文章

  1. POJ 3667 Hotel(线段树 区间合并)

    Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  2. POJ 3667 & 1823 Hotel (线段树区间合并)

    两个题目都是用同一个模板,询问最长的连续未覆盖的区间 . lazy代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度. 区间合并很恶心啊 ...

  3. poj 3667 Hotel (线段树)

    http://poj.org/problem?id=3667 Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 94 ...

  4. poj 3667 Hotel(线段树,区间合并)

    Hotel Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 10858Accepted: 4691 Description The ...

  5. 线段树(区间合并) POJ 3667 Hotel

    题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...

  6. Poj 3667——hotel——————【线段树区间合并】

    Hotel Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13124   Accepted: 5664 Descriptio ...

  7. poj3667 Hotel (线段树 区间合并)

    poj3667 HotelTime Limit: 3000MS Memory Limit: 65536KTotal Submissions: 18925 Accepted: 8242Descripti ...

  8. 【bzoj1593】[Usaco2008 Feb]Hotel 旅馆 线段树区间合并

    题目描述 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N & ...

  9. POJ 2482 Stars in Your Window (线段树区间合并+扫描线)

    这题开始一直被矩形框束缚了,想法一直都是枚举线,但是这样枚举都需要O(n^2)...但是看了别人的思路,感觉这题思想真心很好(PS:开头好浪漫的描述啊,可惜并没有什么用)  题意就是在平面上给你一些星 ...

随机推荐

  1. 学习Hadoop的资料

    1)Cygwin相关资料 (1)Cygwin上安装.启动ssh服务失败.ssh localhost失败的解决方案 地址:http://blog.163.com/pwcrab/blog/static/1 ...

  2. hdu 2372 El Dorado (dp)

    题目链接 题意:给n个数字, 求有k个数字的上升子序列有多少种. 思路:d[i][j]表示 以第i个元素为 子序列的最后一个元素,长度为j的子序列 有多少种. 比赛的时候 光想着用组合数做了..... ...

  3. 一个简单的iBatis入门例子

    一个简单的iBatis入门例子,用ORACLE和Java测试 目录结构: 1.导入iBatis和oracle驱动. 2.创建类Person.java package com.ibeats;import ...

  4. UVa 11542 (高斯消元 异或方程组) Square

    书上分析的太清楚,我都懒得写题解了.=_=|| #include <cstdio> #include <cstring> #include <cmath> #inc ...

  5. busybox filesystem matrix-gui-2.0 undefined function json_encode()

    /******************************************************************************** * matrix-gui-2.0 u ...

  6. shell -Z- d等等代表

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [ -a FILE ]   ...

  7. 保护眼睛,开启浏览器的夜间模式 顺便学下!important的作用

    打开笔记本程序,复制以下代码 *{background-image: none !important; background: none !important; background:#333333 ...

  8. HDU 5489 Removed Interval

    题意:求一段序列中删掉L个连续元素后的LIS. 解法:我的想法很复杂= =怎么说呢……首先用nlogn的方法求LIS得到的序列dp的第i项的意义为上升子序列所有长度为i的序列结尾元素的最小值,那么先倒 ...

  9. [OFBiz]开发 五

    1.初学者例程:OFBiz Tutorial - A Beginners Development Guidehttps://cwiki.apache.org/confluence/display/OF ...

  10. poj1247 bjfu1239水题

    其实就是读题啦,读懂题很简单,就是问一个数组,存不存在一个点,按这个点切成两半,这两半的数字的和是一样的.不多说了,上代码 /* * Author : ben */ #include <cstd ...