CF-46D Parking lot

题意:在一条直线上停车,要求新停入的车有最小前后距离限制(头尾不算),支持停车和开走。

思路:在直线头尾加入一段虚拟的长度,使头尾部不用特殊处理,查询时加入前后距离限制,增删时只计原长。

做完这题,对线段树的理解又清晰了一些。目前遇到的基本都是点树,每个节点维护的是点的数目。所以在询问长度时,头尾需要各缩减1,因为和其他区间相连处会有一个长度为1的半开区间部分,不需要计在节点数内。

原来题目的操作2指的是开走第x个操作的车,在这里WA了一次,蛋疼。题目的数据规模才100,暴力的话复杂度也就1e7。。是不是可以乱搞呢(¯﹃¯)

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls (rt<<1)
#define rs (rt<<1|1)

const int MAXN = 101000;
int lpa[MAXN<<2],rpa[MAXN<<2],mpa[MAXN<<2];
int cover[MAXN<<2];

struct Q{
	int l,r;
}que[MAXN];
int p;

int max(int a,int b) { return a>b?a:b; }

void build(int l, int r, int rt)
{
	cover[rt] = 0;
	lpa[rt] = rpa[rt] = mpa[rt] = r-l+1;
}

void pushdown(int m, int len, int rt)
{
	if(cover[rt] != -1)
	{
		lpa[ls] = rpa[ls] = mpa[ls] = cover[rt]? 0 : len-(len>>1);
		lpa[rs] = rpa[rs] = mpa[rs] = cover[rt]? 0 : (len>>1);
		cover[ls] = cover[rs] = cover[rt];
		cover[rt] = -1;
	}
}

void pushup(int m, int len, int rt)
{
	lpa[rt] = lpa[ls];
	rpa[rt] = rpa[rs];
	if(lpa[rt] == len-(len>>1)) lpa[rt] += lpa[rs];
	if(rpa[rt] == (len>>1)) rpa[rt] += rpa[ls];
	mpa[rt] = rpa[ls] + lpa[rs];
	mpa[rt] = max(mpa[rt], max(lpa[rt], rpa[rt]));
	mpa[rt] = max(mpa[rt], max(mpa[ls], mpa[rs]));
	if(cover[ls]!=-1 && cover[ls]==cover[rs]) cover[rt] = cover[ls];
	else cover[rt] = -1;
}

int query(int len, int l, int r, int rt)
{
	if(l == r)
	{
		return l;
	}
	else
	{
		int m = (l+r)>>1;
		pushdown(m,r-l+1,rt);
		if(mpa[ls] >= len) return query(len, lson);
		else if(rpa[ls]+lpa[rs] >= len) return m-rpa[ls]+1;
		else return query(len, rson);
	}
}

void update(int L, int R, int col, int l, int r, int rt)
{
	if(L<=l && r<=R)
	{
		cover[rt] = col;
		lpa[rt] = rpa[rt] = mpa[rt] = col? 0 : r-l+1;
	}
	else
	{
		int m = (l+r)>>1;
		pushdown(m,r-l+1,rt);
		if(L<=m) update(L,R,col,lson);
		if(R> m) update(L,R,col,rson);
		pushup(m,r-l+1,rt);
	}
}

int main()
{
	int n,b,f;
	int q;
	int op,x;
	while(~scanf("%d%d%d", &n, &b, &f))
	{
		build(-b+1,n+f-1,1);
		scanf("%d", &q);
		p = 0;
		while(q--)
		{
			p ++;
			scanf("%d%d", &op, &x);
			if(op == 1)
			{
		//		printf("mpa[1] = %d\n", mpa[1]);
				if(mpa[1] < x+b+f-1) printf("-1\n");
				else
				{
					int tt = query(x+b+f-1,-b+1,n+f-1,1)+b-1;
					printf("%d\n", tt);
					update(tt,tt+x,1,-b+1,n+f-1,1);
					que[p].l = tt,que[p].r = tt+x;
				}
			}
			else
			{
				update(que[x].l,que[x].r,0,-b+1,n+f-1,1);
			}
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值