线段树区间维护cf46D

D. Parking Lot

题意:0~L停车,与前面的相离发f,后面的相离b,有两种操作:

1 x表示把长度为x的停进去,尽量靠近0

2 x表示把操作编号为x的车开走

如果前面没有车则可以靠0这条边停,这样的话可以在L加上b和f然后再做,线段树维护区间连续空位,左边连续,右边连续和setv(表示当前区间的状态,是不是被占用)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=110;
const int maxm=101000;
int L,b,f,n;
int cars[maxn],care[maxn];
struct IntervalTree
{
    int maxv[maxm<<3],ls[maxm<<3],rs[maxm<<3];
    int setv[maxm<<3];
    void build(int o,int l,int r)
    {
        maxv[o]=ls[o]=rs[o]=r-l+1;
        setv[o]=-1;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
    }
    void maintain(int o,int l,int r)
    {
        if(setv[o]!=-1)
        {
            if(setv[o]==0)maxv[o]=ls[o]=rs[o]=0;
            else maxv[o]=ls[o]=rs[o]=r-l+1;
        }
        else if(r>l)
        {
            maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
            maxv[o]=max(maxv[o],rs[o<<1]+ls[o<<1|1]);
            ls[o]=ls[o<<1];rs[o]=rs[o<<1|1];
            int mid=(l+r)>>1;
            if(ls[o]==mid-l+1)ls[o]+=ls[o<<1|1];
            if(rs[o]==r-mid)rs[o]+=rs[o<<1];
        }
    }
    void pushdown(int o,int l,int r)
    {
        if(setv[o]!=-1)
        {
            setv[o<<1]=setv[o<<1|1]=setv[o];
            setv[o]=-1;
            int mid=(l+r)>>1;

        }
    }
    void update(int o,int l,int r,int q1,int q2,int x)
    {
        if(q1<=l&&r<=q2)
        {
            setv[o]=x;
        }
        else
        {
            int mid=(l+r)>>1;
            pushdown(o,l,r);
            if(q1<=mid)update(o<<1,l,mid,q1,q2,x);else maintain(o<<1,l,mid);
            if(q2>mid)update(o<<1|1,mid+1,r,q1,q2,x);else maintain(o<<1|1,mid+1,r);
        }
        maintain(o,l,r);
    }
    int query(int o,int l,int r,int len)
    {
        if(ls[o]>=len)return l;
        int mid=(l+r)>>1;
        pushdown(o,l,r);
        if(maxv[o<<1]>=len)return query(o<<1,l,mid,len);
        else if(rs[o<<1]+ls[o<<1|1]>=len)return mid-rs[o<<1]+1;
        else return query(o<<1|1,mid+1,r,len);
    }
}tree;
int main()
{
    //freopen("in.txt","r",stdin);
    int op,x;
    scanf("%d%d%d",&L,&b,&f);
    L=b+L+f-1;
    tree.build(1,0,L);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)
        {
            if(tree.maxv[1]>=b+x+f)
            {
                int pos=tree.query(1,0,L,b+x+f);
                cars[i]=pos+b;care[i]=pos+b+x-1;//本来应该是靠0停,但是总长度加了b和f,所以相当于离前一个距离为b
                tree.update(1,0,L,cars[i],care[i],0);
                printf("%d\n",pos);
            }
            else printf("-1\n");
        }
        else tree.update(1,0,L,cars[x],care[x],1);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值