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:开头好浪漫的描述啊,可惜并没有什么用) 题意就是在平面上给你一些星 ...
随机推荐
- hdu 4882 ZCC Loves Codefires (贪心 推导)
题目链接 做题的时候凑的规律,其实可以 用式子推一下的. 题意:n对数,每对数有e,k, 按照题目的要求(可以看下面的Hint就明白了)求最小的值. 分析:假设现在总的是sum, 有两个e1 k1 e ...
- uva10375 Choose and divide
唯一分解定理. 挨个记录下每个质数的指数. #include<cstdio> #include<algorithm> #include<cstring> #incl ...
- iOS开发:为xcode项目添加git仓储
现在apple官网下载Command Line Tools 对应mac版本和xcode版本,记录地址:https://developer.apple.com/downloads/ 找到mac的终端,c ...
- SDOI 2010 and SXOI 2014 地精部落 (递推)
用E[i,j]表示共有i个数字,以1..j开头且一开始下降的方案数的总和.则我们有: E[i,j]:=E[I,J-1]+E[i-1,i-j] 我们先来证明上升与下降的方案是一一对应的. 事实上,若有a ...
- apache开源项目 -- Wicket
[infoq] Apache Wicket是一个功能强大.基于组件的轻量级Web应用框架,能将展现和业务逻辑很好地分离开来.你能用它创建易于测试.调试和支持的高质量Web 2.0应用.假设其他团队交付 ...
- Java [Leetcode 326]Power of Three
题目描述: Given an integer, write a function to determine if it is a power of three. Follow up:Could you ...
- LeetCode: divideInteger
Title: Divide two integers without using multiplication, division and mod operator. If it is overflo ...
- 【转】cocos2d-x 3.2 Fast TileMap
概述 在游戏中常常会有丰富的背景元素,如果直接使用大的背景图实现,这会造成资源浪费.TileMap就是为了解决这问题而产生的.Cocos2d-x支持使用Tile地图编辑器创建的TMX格式的地图. Co ...
- How to Download APK Files from Google Play Store
Evozi, an Android app developer, offers a one-click online APK download app that lets you download t ...
- 开源侧滑菜单SlidingMenu主要方法介绍
SlidingMenu是一个很好使用的侧滑菜单开源项目,它的表现形式类似于DrawerLayout和SlidingDrawer,具体效果如下图所示,左侧为侧滑Menu菜单,右侧黑色部分为内容显示视图C ...