返回顶部
扩大
缩小

2020.3.15 POJ3667 Hotel

问题描述
  奶牛们正在以旅行至桑德贝(Thunder Bay,加拿大中部城市)的方式来增加自己的文化涵养,同时在阳光充沛的苏必利尔湖畔度过一个美好的假期。Bessie,一个能干的旅行代办人,把位于著名的Cumberland街的Bullmouse酒店作为它们旅行时的临时住所。这个巨大的酒店有N个房间,位于酒店极长的走廊的同一侧(全是湖景房)。
  奶牛以及其他游客以一个个旅游团的方式来到酒店登记入住,每个旅游团的大小为D(1<=D<=N)。每个旅行团会向驼鹿Canmuu请求一段连续的房间入住。如果存在长度为Di的一串空房间,他会将房间r至r+Di-1这些房间安排给这个旅行团,否则他将会礼貌的建议它们另寻一个住处。Canmuu总会选择使r最小的那一段房间。
  同时,住在一段连续房间内的游客们也会同时离开酒店。第i次结账用参数X和D表示,代表房间X至X+D-1的房间内的游客离开酒店。某些(或所有)房间可能为空。
  你的任务是帮助Canmuu处理M次入住、离开操作。酒店内一开始没有人。
输入格式
  输入的第一行包含两个整数N,M,表示房间数和操作数。
  下面M行,每行代表一个操作。
  若第一个数为1,则后面会跟着一个数D,表示一个人数为D的旅行团请求入住。
  若第一个数为2,则后面会跟着两个数Xi,Di,表示住在房间Xi至Xi+Di-1的游客离开。
输出格式
  对于每一个入住操作,输出一个数r,可以入住时为最小房间编号,否则为0。
样例输入

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

样例输出

1
4
7
0
5

数据规模和约定
 \(N,M \leq 50000,1 \leq D \leq N,1 \leq X \leq N-D+1。\)

做法:
有修改有询问 \(\rightarrow\) 用数据结构维护(线段树)
对于每个区间维护最长连续0的个数tmax,为了维护tmax,需要从左端起的最长连续0个数lmax和从右端起的最长连续0个数rmax
\(tmax[k]=max(tmax[lc],tmax[rc],rmax[lc]+lmax[rc])\)
\(lmax[k]=lmax[lc] or siz[lc] + lmax[rc]\)
修改:对于每个区间维护懒标记cov
询问:若lc的tmax符合题意,则一直向左找;
若拼起来符合题意,则直接返回
否则一直向右找

代码:

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 50005;

int n, m, op, x, d;
int lmax[N << 2], rmax[N << 2], tmax[N << 2], cov[N << 2], siz[N << 2];

inline void pushup(int k)
{
	lmax[k] = lmax[k << 1];
	rmax[k] = rmax[k << 1 | 1];
	tmax[k] = max(tmax[k << 1], max(tmax[k << 1 | 1], rmax[k << 1] + lmax[k << 1 | 1]));
	if (lmax[k << 1] == siz[k << 1])
		lmax[k] = lmax[k << 1] + lmax[k << 1 | 1];
	if (rmax[k << 1 | 1] == siz[k << 1 | 1])
		rmax[k] = rmax[k << 1 | 1] + rmax[k << 1];
}

inline void pushdown(int k)
{
	if (cov[k] != -1)
	{
		cov[k << 1] = cov[k << 1 | 1] = cov[k];
		if (cov[k] == 1)
		{
			tmax[k << 1] = lmax[k << 1] = rmax[k << 1] = 0;
			tmax[k << 1 | 1] = lmax[k << 1 | 1] = rmax[k << 1 | 1] = 0;
		}
		else
		{
			tmax[k << 1] = lmax[k << 1] = rmax[k << 1] = siz[k << 1];
			tmax[k << 1 | 1] = lmax[k << 1 | 1] = rmax[k << 1 | 1] = siz[k << 1 | 1];
		}
		cov[k] = -1;
	}
}

inline void BuildTree(int k, int l, int r)
{
	siz[k] = r - l + 1;
	if (l == r)
	{
		lmax[k] = rmax[k] = tmax[k] = 1;
		cov[k] = -1;
		return ;
	}
	int mid = l + r >> 1;
	BuildTree(k << 1, l, mid);
	BuildTree(k << 1 | 1, mid + 1, r);
	pushup(k);
}

inline void Update(int k, int l, int r, int L, int R, int x)
{
	if (L <= l && r <= R)
	{
		cov[k] = x;
		lmax[k] = rmax[k] = tmax[k] = x ? 0 : siz[k];
		return ;
	}
	pushdown(k);
	int mid = l + r >> 1;
	if (L <= mid)
		Update(k << 1, l, mid, L, R, x);
	if (mid < R)
		Update(k << 1 | 1, mid + 1, r, L, R, x);
	pushup(k);
}

inline int Query(int k, int l, int r, int x)
{
	if (l == r)
		return l;
	pushdown(k);
	int mid = l + r >> 1;
	if (tmax[k << 1] >= x)
		return Query(k << 1, l, mid, x);
	else if(rmax[k << 1] + lmax[k << 1 | 1] >= x)
		return mid - rmax[k << 1] + 1;
	else
		return Query(k << 1 | 1, mid + 1, r, x);
}

int main()
{
	ios::sync_with_stdio(false);
	cin >> n >> m;
	BuildTree(1, 1, n);
	for (int i = 1; i <= m; ++i)
	{
		cin >> op;
		if (op == 1)
		{
			cin >> d;
			if (tmax[1] < d)
			{
				cout << 0 << endl;
				continue ;
			}
			int pos = Query(1, 1, n, d);
			cout << pos << endl;
			Update(1, 1, n, pos, pos + d - 1, 1);
		}
		else
		{
			cin >> x >> d;
			Update(1, 1, n, x, x + d - 1, 0);
		}
	}
	return 0;
}
posted @ 2020-03-16 20:28  Asasino  阅读(86)  评论(0编辑  收藏  举报