POJ 题目3667 Hotel(线段树,区间更新查询,求连续区间)

Hotel

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 13805   Accepted: 5996

Description

The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation
residence. This immense hotel has N (1 ≤ N ≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).

The cows and other visitors arrive in groups of size Di (1 ≤
Di ≤ N) and approach the front desk to check in. Each group
i
requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers
r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of
r to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and
Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤
XiN-Di+1). Some (or all) of those rooms might be empty before the checkout.

Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..M+1: Line i+1 contains request expressed as one of two possible formats: (a) Two space separated integers representing a check-in request: 1 and
Di (b) Three space-separated integers representing a check-out: 2,
Xi, and Di

Output

* Lines 1.....: For each check-in request, output a single line with a single integer
r, the first room in the contiguous sequence of rooms to be occupied. If the request cannot be satisfied, output 0.

Sample Input

10 6
1 3
1 3
1 3
1 3
2 5 5
1 6

Sample Output

1
4
7
0
5

Source

USACO 2008 February Gold

题意:有一个线段,从1到n。以下m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作

1 w  表示在总区间内查询一个长度为w的可用区间,而且要最靠左,能找到的话返回这个区间的左端点并占用了这个区间,找不到返回0

好像n=10 , 1 3 查到的最左的长度为3的可用区间就是[1,3]。返回1,而且该区间被占用了

2 a len , 表示从单位a開始,清除一段长度为len的区间(将其变为可用。不被占用),不须要输出

ac代码

#include<stdio.h>
#include<string.h>
#define max(a,b) (a>b?a:b)
struct s
{
	int ll,rl,ml,cover;
}node[50050<<2];
void build(int l,int r,int tr)
{
	node[tr].ll=node[tr].rl=node[tr].ml=r-l+1;
	node[tr].cover=-1;
	if(l==r)
		return;
	int mid=(l+r)>>1;
	build(l,mid,tr<<1);
	build(mid+1,r,tr<<1|1);
}
void pushdown(int tr,int m)
{
	if(node[tr].cover!=-1)
	{
		node[tr<<1].cover=node[tr<<1|1].cover=node[tr].cover;
		if(node[tr].cover==0)
		{
			node[tr<<1].ll=node[tr<<1].rl=node[tr<<1].ml=m-(m>>1);
			node[tr<<1|1].ll=node[tr<<1|1].rl=node[tr<<1|1].ml=(m>>1);
		}
		else
		{
			node[tr<<1].ll=node[tr<<1].rl=node[tr<<1].ml=0;
			node[tr<<1|1].ll=node[tr<<1|1].rl=node[tr<<1|1].ml=0;
		}
		node[tr].cover=-1;
	}
}
void pushup(int tr,int m)
{
	node[tr].ll=node[tr<<1].ll;
	node[tr].rl=node[tr<<1|1].rl;
	if(node[tr].ll==m-(m>>1))
		node[tr].ll+=node[tr<<1|1].ll;
	if(node[tr].rl==(m>>1))
		node[tr].rl+=node[tr<<1].rl;
	node[tr].ml=max(node[tr<<1].rl+node[tr<<1|1].ll,max(node[tr<<1].ml,node[tr<<1|1].ml));
}
void update(int L,int R,int l,int r,int tr,int val)
{
	if(L<=l&&R>=r)
	{
		if(val)
		{
			node[tr].ll=node[tr].rl=node[tr].ml=0;
		}
		else
			node[tr].ll=node[tr].rl=node[tr].ml=r-l+1;
		node[tr].cover=val;
		return;
	}
	pushdown(tr,r-l+1);
	int mid=(l+r)>>1;
	if(L>mid)
	{
		update(L,R,mid+1,r,tr<<1|1,val);
	}
	else
		if(R<=mid)
		{
			update(L,R,l,mid,tr<<1,val);
		}
		else
		{
			update(L,mid,l,mid,tr<<1,val);
			update(mid+1,R,mid+1,r,tr<<1|1,val);
		}
	/*if(L<=mid)
		update(L,R,l,mid,tr<<1,val);
	if(R>mid)
		update(L,R,mid+1,r,tr<<1|1,val);*/
	pushup(tr,r-l+1);
}
int query(int w,int l,int r,int tr)
{
	if(l==r)
		return l;
	pushdown(tr,r-l+1);
	int mid=(l+r)>>1;
	if(node[tr<<1].ml>=w)
		return query(w,l,mid,tr<<1);
	else
		if(node[tr<<1].rl+node[tr<<1|1].ll>=w)
			return mid-node[tr<<1].rl+1;
		else
			return query(w,mid+1,r,tr<<1|1);
}
int main()
{
	int n,m;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		build(1,n,1);
		while(m--)
		{
			int op;
			scanf("%d",&op);
			if(op==1)
			{
				int a;
				scanf("%d",&a);
				if(a>node[1].ml)
				{
					printf("0\n");
					continue;
				}
				int p=query(a,1,n,1);
				printf("%d\n",p);
				update(p,p+a-1,1,n,1,1);
			}
			else
			{
				int a,b;
				scanf("%d%D",&a,&b);
				update(a,a+b-1,1,n,1,0);
			}
		}
	}
}
时间: 2024-08-11 00:41:48

POJ 题目3667 Hotel(线段树,区间更新查询,求连续区间)的相关文章

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

Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Stree

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

题目链接~~> 做题感悟:这题是接触线段树区间合并的第一题,做的很纠结. 解题思路: 注意线段树上节点代表的信息 : 每个节点需要维护 lc , rc , mc ,add ,见下图: add 为懒惰标记.假设 i 代表父亲节点编号,左儿子为  i * 2  ,右儿子为 i * 2  + 1 ,那么我们可以得到 : T [ i ] .lc 首先加上左儿子的左边的空格数,然后需要判断一下,如果左儿子的左节点占满了整个左区间时需要再加上右儿子的左边的空格数.同理 T [ i ] .rc 也可以这样得到

POJ 3667 Hotel 线段树 区间合并

题意: 1 输入a:询问是不是有连续长度为a的空房间,有的话住进最左边 2 输入a b:将[a,a+b-1]的房间清空 思路:记录区间中最长的空房间 线段树操作: update:区间替换 query:询问满足条件的最左端点 #include <cstdio> #include <iostream> #include <algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1

POJ - 2155 Matrix (二维树状数组 + 区间改动 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)

POJ - 2155 Matrix Time Limit: 3000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we ha

codevs 1299 线段树 区间更新查询

1299 切水果 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 查看运行结果 题目描述 Description 简单的说,一共N个水果排成一排,切M次,每次切[L,R]区间的所有水果(可能有的水果被重复切),每切完一次输出剩下水果数量 数据已重新装配,不会出现OLE错误 时限和数据范围适当修改,避免数据包过大而浪费空间资源 输入描述 Input Description 第1行共包括2个正整数,分别为N,M. 接下来m行每行两个正整数L,R 输出描述 

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

线段树 + 区间更新 + 模板 ---- poj 3468

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59798   Accepted: 18237 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

线段树区间更新+向量知识——POJ 2991

对应POJ题目:点击打开链接 Crane Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description ACM has bought a new crane (crane -- je?áb) . The crane consists of n segments of various lengths, connected by flexible joints

poj 2528 Mayor&#39;s posters 线段树区间更新

Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at al