POJ 3667 Hotel (线段树区间合并)
题目链接: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 (线段树区间合并)的更多相关文章
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- POJ 3667 & 1823 Hotel (线段树区间合并)
两个题目都是用同一个模板,询问最长的连续未覆盖的区间 . lazy代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度. 区间合并很恶心啊 ...
- poj 3667 Hotel (线段树)
http://poj.org/problem?id=3667 Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 94 ...
- poj 3667 Hotel(线段树,区间合并)
Hotel Time Limit: 3000MSMemory Limit: 65536K Total Submissions: 10858Accepted: 4691 Description The ...
- 线段树(区间合并) POJ 3667 Hotel
题目传送门 /* 题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边 输入 2 a b:将[a,a+b-1]的房间清空 线段树(区间合并):lsum[]统计从左端点起最长连续空房间 ...
- Poj 3667——hotel——————【线段树区间合并】
Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 13124 Accepted: 5664 Descriptio ...
- poj3667 Hotel (线段树 区间合并)
poj3667 HotelTime Limit: 3000MS Memory Limit: 65536KTotal Submissions: 18925 Accepted: 8242Descripti ...
- 【bzoj1593】[Usaco2008 Feb]Hotel 旅馆 线段树区间合并
题目描述 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N & ...
- POJ 2482 Stars in Your Window (线段树区间合并+扫描线)
这题开始一直被矩形框束缚了,想法一直都是枚举线,但是这样枚举都需要O(n^2)...但是看了别人的思路,感觉这题思想真心很好(PS:开头好浪漫的描述啊,可惜并没有什么用) 题意就是在平面上给你一些星 ...
随机推荐
- ruby安装插件报错
有时候我们需要安装ruby插件的时候,会报如下错误: ERROR: Could not find a valid gem 'rdiscount' (>= 0), here is why: Un ...
- 二维树状数组(水题) POJ1195
前段时间遇到线段树过不了,树状数组却过了的题.(其实线段树过得了的) 回忆了下树状数组. 主要原理,还是二进制位数,每一项的和表示其为它的前((最后一位1及其后)的二进制数)和,可从二进制图来看.(用 ...
- 基于XMPP的即时通信系统的建立(六)— 开发环境搭建
服务器端 新建空工程 使用Eclipse新建名为openfire的空java工程. 导入源代码 这里使用的是openfire的openfire_src_3_10_3.zip源码. 导入后将目录src/ ...
- UVa 580 (递推) Critical Mass
题意: 有两种盒子分别装有铀(U)和铅(L),现在把n个盒子排成一列(两种盒子均足够多),而且要求至少有3个铀放在一起,问有多少种排放方法. 分析: n个盒子排成一列,共有2n中方案,设其中符合要求的 ...
- css配合js模拟的select下拉框
css配合js模拟的select下拉框 <!doctype html> <html> <head> <meta charset="utf-8&quo ...
- WTL汉化版2013.10.15
汉化内容: 2013.10.15 版本:当前可下载Trunk最新版,wtl-code-467-trunk.zip 汉化内容: 1.应用向导的部分汉化,考虑到部分词汇的表述问题,只汉化无影响部分 2.资 ...
- Android Dialog使用举例
在Android开发中,我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框,在我们使用Android的过程中,我归纳了一 ...
- UITextField限制字数的方法
转:http://blog.csdn.net/marujunyy/article/details/9985411 在输入东西的时候,如果想限制最大字数,可以用下面方法: - (BOOL)textFie ...
- hdu 3938 Portal(并查集+离线+kruskal)2011 Multi-University Training Contest 10
搜了题解才把题搞明白.明白之后发现其实题意很清晰,解题思路也很清晰,只是题目表述的很不清晰…… 大意如下—— 给你一个无向图,图中任意两点的距离是两点间所有路径上的某一条边,这条边需要满足两个条件:1 ...
- C语言内存地址基础
来源:http://blog.jobbole.com/44845/ 从计算机内存的角度思考C语言中的一切东东,是挺有帮助的.我们可以把计算机内存想象成一个字节数组,内存中每一个地址表示 1 字节.比方 ...