POJ 3667 Hotel (线段树 区间更新查找)

版权声明:From: http://blog.csdn.net/tju_tahara https://blog.csdn.net/TJU_Tahara/article/details/52318985
Hotel
Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 16205   Accepted: 7047

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 ≤ Xi ≤ N-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 D(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


题意:

让人们住进旅馆里面,需要连续的n个房间。同时可以清空连续的一些房间。

思路:

比较经典的线段树问题,但是不加lazy操作貌似会TLE。记录下来从l开始的最大值和从r开始的最大值便于合并即可。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <cmath>
#define lc (n << 1)
#define rc (n << 1 | 1)
#define mid (l + r >> 1)
#define MAX 80000
using namespace std;

struct node{
	int sum, l, r, lz;
}sgm[MAX * 4];

inline void lazy(int n, int l, int r){
	if(sgm[n].lz == 1){
		sgm[lc].sum = sgm[lc].l = sgm[lc].r = mid - l + 1;
		sgm[rc].sum = sgm[rc].l = sgm[rc].r = r - mid;
		sgm[lc].lz = sgm[rc].lz = 1;
		sgm[n].lz = 0;
	}
	else if(sgm[n].lz == -1){
		sgm[lc].sum = sgm[lc].l = sgm[lc].r = 0;
		sgm[rc].sum = sgm[rc].l = sgm[rc].r = 0;
		sgm[lc].lz = sgm[rc].lz = -1;
		sgm[n].lz = 0;
	}
}

void build(int n, int l, int r){
	sgm[n].lz = 0;
	sgm[n].sum = sgm[n].l = sgm[n].r = r - l + 1;
	if(l == r) return;
	build(lc, l, mid);
	build(rc, mid + 1, r);
}

inline void pushdown(int n, int l, int r){
	if(sgm[lc].l == mid - l + 1) sgm[n].l = sgm[lc].l + sgm[rc].l;
	else sgm[n].l = sgm[lc].l;
	if(sgm[rc].r == r - mid) sgm[n].r = sgm[rc].r + sgm[lc].r;
	else sgm[n].r = sgm[rc].r;
	sgm[n].sum = max(sgm[lc].sum, sgm[rc].sum);
	sgm[n].sum = max(sgm[n].sum, sgm[lc].r + sgm[rc].l);
}

int get(int n, int l, int r, int num){
	if(sgm[n].sum < num) return 0;
	int res;
	if(sgm[n].sum == num && r - l + 1 == num) return l;
	lazy(n, l, r);
	if(sgm[lc].sum >= num) 
		res = get(lc, l, mid, num);
	else if(sgm[lc].r + sgm[rc].l >= num)
		res = mid - sgm[lc].r + 1;
	else
		res = get(rc, mid + 1, r, num);
	return res;
}

void clean(int n, int l, int r, int L, int R, int num){
	if(l == L && r == R){
		if(num == 1){
		sgm[n].l = sgm[n].r = sgm[n].sum = r - l + 1;
		sgm[n].lz = 1;
		}
		else{
			sgm[n].l = sgm[n].r = sgm[n].sum = 0;
			sgm[n].lz = -1;
		}
		return;
	}
	lazy(n, l, r);
	if(L > mid) clean(rc, mid + 1, r, L, R, num);
	else if(R <= mid) clean(lc, l, mid, L, R, num);
	else{
		clean(lc, l, mid, L, mid ,num);
		clean(rc, mid + 1, r, mid + 1, R, num);
	}
	pushdown(n, l, r);
}


int main()
{
	int tot, num, i, res, ord, l, r;
	scanf("%d%d", &tot, &num);
	build(1,1,tot);
	for(i = 0; i < num; i++){
		scanf("%d", &ord);
		if(ord == 1){
			scanf("%d", &l);
			res = get(1,1,tot, l);
			if(res) clean(1,1,tot,res, res + l - 1, -1);
			printf("%d\n", res);
		}
		else{
			scanf("%d%d", &l, &r);
			clean(1,1,tot,l, l + r - 1, 1);
		}
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/TJU_Tahara/article/details/52318985