POJ 3667 Hotel (线段树区间最大连续长度)

求长度为K的连续区间的左端点的最小值

check in 的时候,先查寻出左端点r,然后插入线段[r, r+D-1]

check out 的时候,直接删除线段[X, X+D-1]

要使用lazy标记,否则TLE

代码写的有点。。。。

/*===============================================================
*   Copyright (C) 2012 All rights reserved.
*   
*   file: 3667_Hotel.cpp
*   author: ivapple
*   date: 2012-09-22
*   description: 
*
*   update log: 
*
================================================================*/
#include <cstdlib>
#include <cstdio>

#include <iostream>

#define out(x) (cout<<#x<<": "<<x<<endl)

#define FOR(i,s,t) for(i=s; i<t; i++)

using namespace std;

template<class T>void show(T a, int n){int i; for(i=0;i<n;i++)cout<<a[i]<<" ";cout<<endl;}

template<class T>void show(T a, int r, int l){int i; for(i=0;i<r;i++)show(a[i],l);cout<<endl;}

const int kMaxNum = 50000;
struct SegTree
{
	int s, e;
	int lc, rc;
	int lv, rv, maxv;
	int cover;
}tree[4*kMaxNum];
int id = -1;

int Max(int a, int b, int c)
{
	a = a>b?a:b;
	return c>a?c:a;
}
void BuildTree(int l, int r)
{
	int root = ++id;
	int mid;
	tree[root].s = l;
	tree[root].e = r;
	tree[root].lv = r-l+1;
	tree[root].rv = r-l+1;
	tree[root].maxv = r-l+1;
	if (l < r)
	{
		mid = (l+r)/2;
		tree[root].lc = id+1;
		BuildTree(l, mid);
		tree[root].rc = id+1;
		BuildTree(mid+1,r);
	}
}
int InsertDown(int root)
{
	int lc, rc;
	lc = tree[root].lc;
	rc = tree[root].rc;
	if (lc)
	{
		tree[lc].cover = 1;
		tree[lc].lv = 0;
		tree[lc].rv = 0;
		tree[lc].maxv = 0;
	}
	if (rc)
	{
		tree[rc].cover = 1;
		tree[rc].lv = 0;
		tree[rc].rv = 0;
		tree[rc].maxv = 0;
	}
	tree[root].cover = 0;
}
int DeleteDown(int root)
{
	int lc, rc;
	lc = tree[root].lc;
	rc = tree[root].rc;
	if (lc)
	{
		tree[lc].cover = -1;
		tree[lc].lv = tree[lc].e-tree[lc].s+1;
		tree[lc].rv = tree[lc].e-tree[lc].s+1;
		tree[lc].maxv = tree[lc].e-tree[lc].s+1;
	}
	if (rc)
	{
		tree[rc].cover = -1;
		tree[rc].lv = tree[rc].e-tree[rc].s+1;
		tree[rc].rv = tree[rc].e-tree[rc].s+1;
		tree[rc].maxv = tree[rc].e-tree[rc].s+1;
	}
	tree[root].cover = 0 ;
}

int Query(int root, int len)
{
	int lc, rc;
	if (tree[root].lv >= len) 
		return tree[root].s;
	else
	{
		if (tree[root].maxv < len) 
			return 0;
		else
		{
			lc = tree[root].lc;
			rc = tree[root].rc;
			if (tree[lc].maxv >= len)
			{
				if (tree[root].cover == 1)
					InsertDown(root);
				if (tree[root].cover == -1)
					DeleteDown(root);
				return Query(lc, len);
			}
			else
			{
				if (tree[lc].rv+tree[rc].lv >= len)
					return tree[lc].e-tree[lc].rv+1;
				else
				{
					if (tree[rc].maxv >= len)
					{
						if (tree[root].cover == 1)
							InsertDown(root);
						if (tree[root].cover == -1)
							DeleteDown(root);
						return Query(rc, len);
					}
				}
			}
		}
	}

}
int Update(int root)
{
	int lc = tree[root].lc;
	int rc = tree[root].rc;
	int mid = (tree[root].s + tree[root].e)/2;
	tree[root].lv = tree[lc].lv + ((tree[lc].lv+tree[lc].s-1)>=mid?tree[rc].lv:0);
	tree[root].rv = tree[rc].rv + ((tree[rc].e-tree[rc].rv)<=mid?tree[lc].rv:0);
	int tmp = tree[lc].rv + tree[rc].lv;
	int max = Max(tree[root].lv, tree[root].rv, tmp);
	tree[root].maxv = Max(tree[lc].maxv, tree[rc].maxv, max);
}
void Insert(int root, int l, int r)
{
	if (l<=tree[root].s&&tree[root].e<=r)
	{
		tree[root].cover = 1;
		tree[root].lv = 0;
		tree[root].rv = 0;
		tree[root].maxv = 0;
		return;
	}
	if (tree[root].cover == 1)
		InsertDown(root);
	if (tree[root].cover == -1)
		DeleteDown(root);
	int mid, lc, rc;
	lc = tree[root].lc;
	rc = tree[root].rc;
	mid = (tree[root].s+tree[root].e)/2;
	if (l <= mid)
		Insert(lc, l, r);
	if (r > mid)
		Insert(rc, l, r);
	Update(root);
}
void Delete(int root, int l, int r)
{
	if (l<=tree[root].s&&tree[root].e<=r)
	{
		tree[root].cover = -1;
		tree[root].lv = tree[root].e-tree[root].s+1;
		tree[root].rv = tree[root].e-tree[root].s+1;
		tree[root].maxv = tree[root].e-tree[root].s+1;
		return;
	}
	if (tree[root].cover == 1)
		InsertDown(root);
	if (tree[root].cover == -1)
		DeleteDown(root);
	int mid, lc, rc;
	lc = tree[root].lc;
	rc = tree[root].rc;
	mid = (tree[root].s+tree[root].e)/2;
	if (l <= mid)
		Delete(lc, l, r);
	if (r > mid)
		Delete(rc, l, r);
	Update(root);
}

int N, M;
int main()
{
	int i;
	int op, D, X;
	int r;
#ifndef ONLINE_JUDGE
	freopen("test.txt", "r", stdin);
#endif
	scanf("%d%d", &N, &M);
	BuildTree(1, N);
	for (i=0; i<M; i++)
	{
		scanf("%d",&op);
		if (op == 1)
		{
			scanf("%d", &D);
			r = Query(0, D);
			if (r == 0)
				printf("0\n");
			else
			{
				printf("%d\n", r);
				Insert(0, r, r+D-1);
			}
		}
		if (op == 2)
		{
			scanf("%d%d", &X, &D);
			Delete(0, X, X+D-1);
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值