poj3667 线段树

第二次做这种维护连续的区间问题
经典的维护连续的区间 跟poj2892类似
但是本篇的代码风格写的比上次要好些
题意:一开始一个酒店有n间空房
有两种操作 1 需要x间连续的房间要入住,输出连续的x间房的最左边的房号
  2 从第x间房之后的y间房清空。
方法:入住的时候查询线段树所维护的连续区间找到最左的一个标号,输出
然后更新线段树

退房的时候更新线段树,清空。

	#include <map>
	#include <queue>
	#include <stack>
	#include <deque>
	#include <math.h>
	#include <string>
	#include <vector>
	#include <stdio.h>
	#include <iostream>
	#include <string.h>
	#include <algorithm>
	#include <functional>
	#define mem(a) memset(a,0,sizeof(a));
	#define mem_1(a) memset(a,-1,sizeof(a));
	#define sf(a) scanf("%d",&a)
	#define sff(a,b) scanf("%d%d",&a,&b)
	#define sfff(a,b,c) scanf("%d%d%d",&a,&b,&c)
	#define lson l,mid,i<<1
	#define rson mid+1,r,i<<1|1
	const int INF = 0x7FFFFFFF;
	const int MAXN = 50100;
	const double PI = acos(-1.0);
	const double esp = 1e-10;
	using namespace std;
	struct node
	{
		 int l,r,ls,rs,ms;
		 int lazy;
		 int mid(){return (l+r) >> 1;}
	}Tree[MAXN<<2];
	void pushDown(int i)
	{
		if(Tree[i].lazy!=-1)
		{
			Tree[i<<1].lazy = Tree[i].lazy;
			Tree[i<<1|1].lazy = Tree[i].lazy;
			int ll =  Tree[i<<1].r - Tree[i<<1].l +1;
	        int rr = Tree[i<<1|1].r - Tree[i<<1|1].l +1;
	        Tree[i<<1].ls = Tree[i<<1].rs = Tree[i<<1].ms = Tree[i<<1].lazy ? 0 : ll;
	        Tree[i<<1|1].ls = Tree[i<<1|1].rs = Tree[i<<1|1].ms = Tree[i<<1|1].lazy ? 0 : rr;
	        Tree[i].lazy = -1;
		}
	}
	void pushUp(int i)
	{
		int ll = Tree[i<<1].r - Tree[i<<1].l + 1;
		int rr = Tree[i<<1|1].r - Tree[i<<1|1].l +1;
		Tree[i].ls = Tree[i<<1].ls;
		Tree[i].rs = Tree[i<<1|1].rs;
		if(Tree[i].ls == ll)
			Tree[i].ls += Tree[i<<1|1].ls;
		if(Tree[i].rs == rr)
			Tree[i].rs += Tree[i<<1].rs;
		Tree[i].ms = max(max(Tree[i<<1].ms,Tree[i<<1|1].ms),Tree[i<<1].rs + Tree[i<<1|1].ls);
	}
	void build_tree(int l,int r,int i)
	{
		Tree[i].l = l;
		Tree[i].r = r;
		Tree[i].lazy = -1;
		Tree[i].ls = Tree[i].ms = Tree[i].rs = r - l + 1;
		if(l == r)  return ;
	    int mid = (l+r) >> 1;
		build_tree(lson);
		build_tree(rson);
		pushUp(i);
	}

	void updata_tree(int l,int r,int i,int need)
	{
		if(Tree[i].l == l && Tree[i].r == r )
		{
			Tree[i].ms = Tree[i].ls  = Tree[i].rs = need ? 0 : (r+1-l);
			Tree[i].lazy = need;
			return ;
		}
		pushDown(i);
		int mid = Tree[i].mid();
		if(r <= mid) updata_tree(l,r,i<<1,need);
		else if(mid < l) updata_tree(l,r,i<<1|1,need);
		else
		{
			updata_tree(lson,need);
			updata_tree(rson,need);
		}
		pushUp(i);
	}
	int Query(int need,int i)
	{
		if(Tree[i].l == Tree[i].r)
			return Tree[i].l;
		pushDown(i);
		int mid = Tree[i].mid();
		if(Tree[i<<1].ms >= need)
			return Query(need,i<<1);
		else if(Tree[i<<1].rs + Tree[i<<1|1].ls >=need)
			return mid - Tree[i<<1].rs+1;
		else
			return Query(need,i<<1|1);

	}
	int main()
	{
		int n,m,x,num;
		sff(n,m);
		build_tree(1,n,1);
		while(m--)
		{
			sf(x);
			if(x==1)
			{
				sf(num);
				if(Tree[1].ms < num) puts("0");
				else
				{
					int ans = Query(num,1);
					printf("%d\n",ans);
					updata_tree(ans,ans+num-1,1,1);
				}
			}
			else
			{
			    int form;
				sff(form,num);
				updata_tree(form,form+num-1,1,0);
			}
		}
		return 0;
	}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值