经典线段树的题。

每个节点存储的信息:左端点连续空房间的长度,右端点连续空房间长度,连续空房间的最大长度。

由于要求每次必须从尽量靠左边的位置进行居住,那么搜索时应尽量让区间起始位置更小:

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 线段树的更多相关文章

  1. poj 2886 线段树+反素数

    Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12744   Acc ...

  2. [USACO08FEB]酒店Hotel 线段树

    [USACO08FEB]酒店Hotel 线段树 题面 其实就是区间多维护一个lmax,rmax(表示从左开始有连续lmax个空房,一直有连续rmax个空房到最右边),合并时讨论一下即可. void p ...

  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 转载自:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html [题目链接]Hotel [题目类型]线段树 ...

  5. POJ 1823 Hotel 线段树

    题目链接 线段树的区间合并. 和上一题差不多....第三种操作只需要输出maxx[1]的值就可以. #include <iostream> #include <vector> ...

  6. poj 3468(线段树)

    http://poj.org/problem?id=3468 题意:给n个数字,从A1 …………An m次命令,Q是查询,查询a到b的区间和,c是更新,从a到b每个值都增加x.思路:这是一个很明显的线 ...

  7. POJ——3264线段树

    题目: 输入两个数(m,n),m表示牛的头数,n表示查询的个数.查询时输入两个数(x,y),表示查询范围的起始值和终止值,查询结果是,这个区间内牛重量的最大值减去牛重量的最小值,数量级为1000,00 ...

  8. POJ 2828 线段树(想法)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 15422   Accepted: 7684 Desc ...

  9. PKU 3667 Hotel(线段树)

    Hotel The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

随机推荐

  1. WebP 图片实践之路

    我们会从三部分来聊聊webp这个话题. 什么是webp,它有什么用? 使用webp的常规方法以及优劣. 我们是如何用上webp的. PS:如果是对webp有一定了解的朋友,建议直接看第三部分.因为是讲 ...

  2. char (*p)[]和char *p[]的区别

    理解的关键在于: 1. []的优先级高于*,(*p)[]理解为指向一个数组,*(p[])存放指针的数组 2. char (*p)[SIZE]:指向一维数组的指针,一维数组只能有SIZE个元素 char ...

  3. sping中防止定时任务多处运行解决方法

    @Servicepublic class TimerJobService implements LzhTimerJobDao{ Logger logger = LoggerFactory.getLog ...

  4. Python 斐波那契数列练习

    # coding=gbk # 迭代法---1 def fibonacci (n): if n == 0 or n == 1: return n else : a = 0 b = 1 for i in ...

  5. WebSphere--部署Servlet

    在WebSphere应用服务器上部署 Servlet需要四个步骤:编译 Servlet 或 Web 应用程序.将类文件放到 WebSphere应用服务器上.将相关的 HTML.JSP 和 SHTML ...

  6. MySQL存储过程中declare和set定义变量的区别

    在存储过程中常看到declare定义的变量和@set定义的变量.简单的来说,declare定义的类似是局部变量,@set定义的类似全局变量. 1.declare定义的变量类似java类中的局部变量,仅 ...

  7. 优秀的基于VUE移动端UI框架合集

    1. vonic 一个基于 vue.js 和 ionic 样式的 UI 框架,用于快速构建移动端单页应用,很简约,是我喜欢的风格 star 2.3k 中文文档 在线预览 2.vux 基于WeUI和Vu ...

  8. Matlab产生TestBeach所需要的波形数据

    在用vivado仿真的时候,很多情况下需要自己产生波形来代替AD采样波形.以前的做法都是用DDS内部产生所需要的波形来模仿外部输入,后来发现这种做法不仅麻烦,而且不易修改,对仿真很不友好.于是改用ma ...

  9. Ajax异步信息抓取方式

    淘女郎模特信息抓取教程 源码地址: cnsimo/mmtao 网址:https://0x9.me/xrh6z   判断一个页面是不是Ajax加载的方法: 查看网页源代码,查找网页中加载的数据信息,如果 ...

  10. Core Animation 文档翻译 (第五篇)

      构建Layer层次结构 在APP中大多数情况下,将Layer和View对象结合使用是Layer最好的使用方式.然而,很多时候我们可能需要通过添加单独的Layer对象,以便增加视图继承层次:当为了提 ...