poj Hotel 线段树
经典线段树的题。
每个节点存储的信息:左端点连续空房间的长度,右端点连续空房间长度,连续空房间的最大长度。
由于要求每次必须从尽量靠左边的位置进行居住,那么搜索时应尽量让区间起始位置更小:
1.如果当前区间的最大空房间长度小于要寻找的长度,说明不会找到符合的区间,直接退出。
2.如果左子区间的最大空房间长度大于等于要寻找的长度,那么应该进入左子区间查找。
3.否则,如果左子区间的右端点连续空房间长度 + 右子区间的左端点连续空房间的长度 大于等于
要寻找的长度则直接返回左子区间右端点起始空房间下标。
4.否则,进入右区间寻找。
AC代码:
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 2e5;
struct node{
int l, r;
int len, lenl, lenr;
int tag; //0代表全空 1代表全满 -1代表混杂
}t[maxn];
void build(int l, int r, int cur){
t[cur].l = l, t[cur].r = r;
t[cur].len = t[cur].lenl = t[cur].lenr = r - l + 1;
t[cur].tag = 0;
if(l == r) return;
int mid = (l + r) / 2;
build(l, mid, cur << 1);
build(mid + 1, r, (cur << 1) + 1);
}
void lazy(int cur){
if(t[cur].l == t[cur].r) return;
if(t[cur].tag >= 0) { //覆盖
int l = cur << 1, r = (cur << 1) + 1;
int val;
if(t[cur].tag == 0) val = t[l].r - t[l].l + 1;
else val = 0;
t[l].len = t[l].lenl = t[l].lenr = val;
if(t[cur].tag == 0) val = t[r].r - t[r].l + 1;
else val = 0;
t[r].len = t[r].lenl = t[r].lenr = val;
t[r].tag = t[l].tag = t[cur].tag;
}
}
int search(int len, int cur){
if(t[cur].len < len) return 0;
int l = t[cur].l, r = t[cur].r;
if(l == r) return l;
lazy(cur);
if(t[cur << 1].len >= len) return search(len, cur << 1);
else if(t[cur << 1].lenr + t[(cur << 1) + 1].lenl >= len) return t[cur << 1].r - t[cur << 1].lenr + 1;
else if(t[(cur << 1) + 1].len >= len) return search(len, (cur << 1) +1);
}
void update(int l, int r, int tag, int cur){
int l1 = t[cur].l, r1 = t[cur].r;
if(l1 == l && r1 == r){
t[cur].tag = tag;
int val;
if(tag) val = 0;
else val = r1 - l1 + 1;
t[cur].len = t[cur].lenl = t[cur].lenr = val;
return;
}
lazy(cur);
int mid = (l1 + r1) / 2;
if(r <= mid) update(l, r, tag, cur << 1);
else if(l >= mid + 1) update(l, r, tag, (cur << 1) + 1);
else {
update(l, mid, tag, cur << 1);
update(mid + 1, r, tag, (cur << 1) + 1);
}
int c1 = cur << 1, c2 = (cur << 1) + 1;
int w = t[c1].lenr + t[c2].lenl;
t[cur].lenl = t[c1].lenl, t[cur].lenr = t[c2].lenr;
if(t[c1].tag == 0) t[cur].lenl = w;
if(t[c2].tag == 0) t[cur].lenr = w;
t[cur].len = max(t[c1].len, t[c2].len);
t[cur].len = max(w, t[cur].len);
t[cur].len = max(t[cur].len, t[cur].lenr);
t[cur].len = max(t[cur].len, t[cur].lenl);
if(t[cur].len == 0) t[cur].tag = 1;
else if(t[cur].len == r1 - l1 + 1) t[cur].tag = 0;
else t[cur].tag = -1;
}
int main(){
int n,q;
while(scanf("%d%d", &n, &q) == 2){
build(1, n, 1);
int a, b, c;
for(int i = 0; i < q; ++i){
scanf("%d", &a);
if(a == 1){
scanf("%d", &b);
int x = search(b, 1);
printf("%d\n", x);
if(x != 0) update(x, x + b - 1, 1, 1);
}
else {
scanf("%d%d", &b, &c);
update(b, b + c - 1, 0, 1);
}
}
}
return 0;
}
如有不当之处欢迎指出!
poj Hotel 线段树的更多相关文章
- poj 2886 线段树+反素数
Who Gets the Most Candies? Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 12744 Acc ...
- [USACO08FEB]酒店Hotel 线段树
[USACO08FEB]酒店Hotel 线段树 题面 其实就是区间多维护一个lmax,rmax(表示从左开始有连续lmax个空房,一直有连续rmax个空房到最右边),合并时讨论一下即可. void p ...
- poj 3667 Hotel (线段树)
http://poj.org/problem?id=3667 Hotel Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 94 ...
- POJ 3667 Hotel(线段树 区间合并)
Hotel 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...
- POJ 1823 Hotel 线段树
题目链接 线段树的区间合并. 和上一题差不多....第三种操作只需要输出maxx[1]的值就可以. #include <iostream> #include <vector> ...
- poj 3468(线段树)
http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...
- POJ——3264线段树
题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...
- POJ 2828 线段树(想法)
Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 15422 Accepted: 7684 Desc ...
- PKU 3667 Hotel(线段树)
Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...
随机推荐
- form表单action=""的作用
看项目时发现action="",可仍旧提交到后台相关页面了.查了一下,action=""相当于当前页面刷新,不过页面按照form表单提交参数到后台@参考文章
- alwaysOn中关于维护计划的应用方案
由于alwaysOn环境下主副本所在的实际服务器不固定, 所以我目前采取的方案是创建维护计划的时候, 在各个服务器上创建一份维护计划. (假设有2个服务器需要故障转移, 那么就在这两个服务器上分别创建 ...
- 【转】linux shell 逻辑运算符、逻辑表达式
shell的逻辑运算符 涉及有以下几种类型,因此只要适当选择,可以解决很多复杂的判断. 一.逻辑运算符 逻辑卷标表示意思 1.关于档案与目录的侦测逻辑卷标! -f常用!侦测‘档案’是否存在 eg: ...
- 系统uid在1-499的原因
1.因为是保留给系统使用的UID,为了与用户设置的账户区分,防止冲突. 2.并没有其他特别的意义, 3.也叫作虚拟用户,除了0之外,所有的UID在使用上并没有任何区别. 4.linux中文件和程序都要 ...
- 《.NET 设计规范》第 6 章:扩展性设计
第 6 章:扩展性设计 6.1 扩展机制 考虑用不包含任何虚成员或受保护的成员的非密封类来为框架提供扩展性.这种方法所提供的扩展性广受用户欢迎,而且它的开销也不高. 考虑将受保护的成员用于高级的定制方 ...
- Technical debt
What is Technial debt? Technical debt is not bug. It is that the feature can work, but it is not a p ...
- 以C语言为例的程序性能优化 --《深入理解计算机系统》第五章读书笔记
其实大多数的编译器本身就能提供一些简单的优化,比如gcc就能通过使用 -O2 或者 -O3 的选项来优化程序.但编译器的优化始终也是有限,因为它必须小心翼翼保证优化过程不对程序的功能有改动.故而程序员 ...
- Django的ModelForm
基于django.forms.ModelForm:与模型类绑定的Form 先定义一个ModelForm类,继承ModelForm类 from django.forms import ModelForm ...
- Django(三) ORM操作
一.DjangoORM 创建基本类型及生成数据库表结构 1.简介 ORM:关系对象映射.定义一个类自动生成数据库的表结构. 数据库常用的数据类型 : 数字 字符串 时间 ORM分为两种类型: 主流都是 ...
- wxPython实现在浏览器中打开链接
需要用到webbrowser模块 代码超简单: import webbrowserwebbrowser.open('http://www.wangxing.com') webbrowser.open( ...