【USACO 2008FEB】 旅馆

【题目链接】

          点击打开链接

【算法】

          线段树

          对于一个节点,记录它从左端点延伸的最多的空房间的个数,从右端点延伸的最多的空房间个数,和该区间最多的连续

          空房间个数

【代码】

          

#include<bits/stdc++.h>
using namespace std;
#define MAXN 50010

int n,m,opt,pos,x,d;

struct SegmentTree
{
		struct Node
		{
				int l,r,lm,rm,mx,tag;
		} Tree[MAXN*4];
		inline void build(int index,int l,int r)
		{
				int mid;
				Tree[index].l = l;
				Tree[index].r = r;
				Tree[index].lm = Tree[index].rm = Tree[index].mx = r - l + 1;
				Tree[index].tag = -1;
				if (l == r) return;
				mid = (l + r) >> 1;
				build(index<<1,l,mid);
				build(index<<1|1,mid+1,r);
		}
		inline void pushdown(int index)
		{
				int ql = Tree[index].l,qr = Tree[index].r;
				int mid = (ql + qr) >> 1;
				if (ql == qr) return;
				if (Tree[index].tag == 0)
				{
						Tree[index<<1].lm = Tree[index<<1].rm = Tree[index<<1].mx = mid - ql + 1;
						Tree[index<<1|1].lm = Tree[index<<1|1].rm = Tree[index<<1|1].mx = qr - mid;
						Tree[index<<1].tag = Tree[index<<1|1].tag = 0;
						Tree[index].tag = -1;
				}
				if (Tree[index].tag == 1)
				{
						Tree[index<<1].lm = Tree[index<<1].rm = Tree[index<<1].mx = 0;
						Tree[index<<1|1].lm = Tree[index<<1|1].rm = Tree[index<<1|1].mx = 0;
						Tree[index<<1].tag = Tree[index<<1|1].tag = 1;
						Tree[index].tag = -1;
				}
		}
		inline void update(int index)
		{
				int ql = Tree[index].l,qr = Tree[index].r;
				int mid = (ql + qr) >> 1;
				if (Tree[index<<1].lm == mid - ql + 1) Tree[index].lm = Tree[index<<1].lm + Tree[index<<1|1].lm;
				else Tree[index].lm = Tree[index<<1].lm;
				if (Tree[index<<1|1].rm == qr - mid) Tree[index].rm = Tree[index<<1|1].rm + Tree[index<<1].rm;
				else Tree[index].rm = Tree[index<<1|1].rm;
				Tree[index].mx = max(max(Tree[index<<1].mx,Tree[index<<1|1].mx),Tree[index<<1].rm+Tree[index<<1|1].lm);
		}
		inline void modify(int index,int l,int r,int val)
		{
				int mid,ql,qr;
				if (Tree[index].l == l && Tree[index].r == r)
				{
						Tree[index].lm = Tree[index].rm = Tree[index].mx = (val ^ 1) * (r - l + 1);
						Tree[index].tag = val;
				} else
				{
						pushdown(index);
						ql = Tree[index].l;
						qr = Tree[index].r;
						mid = (ql + qr) >> 1;
						if (mid >= r) modify(index<<1,l,r,val);
						else if (mid + 1 <= l) modify(index<<1|1,l,r,val);
						else 
						{
								modify(index<<1,l,mid,val);
								modify(index<<1|1,mid+1,r,val);
						}
						update(index);
				}
		}
		inline int query_pos(int index,int d)
		{
				int mid,ql,qr;
				ql = Tree[index].l; qr = Tree[index].r;
				mid = (ql + qr) >> 1;
				if (ql == qr) return ql;
				pushdown(index);
				if (Tree[index<<1].mx >= d) return query_pos(index<<1,d);
				else if (Tree[index<<1].rm + Tree[index<<1|1].lm >= d) return mid - Tree[index<<1].rm + 1;
				else return query_pos(index<<1|1,d);
		}
		inline int query()
		{
				return Tree[1].mx;
		}
} T;

template <typename T> inline void read(T &x)
{
    int f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; }
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
template <typename T> inline void write(T x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) write(x/10);
    putchar(x%10+'0');
}
template <typename T> inline void writeln(T x)
{
    write(x);
    puts("");
}

int main() {
		
		read(n); read(m);
		T.build(1,1,n);
		while (m--)
		{
				read(opt);
				if (opt == 1)
				{
						read(d);
						if (T.query() < d) writeln(0);
						else 
						{
								pos = T.query_pos(1,d);
								writeln(pos);
								T.modify(1,pos,pos+d-1,1);
						}
				} else
				{
						read(x); read(d);
						T.modify(1,x,x+d-1,0);
				}
		}
		
		return 0;
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值