Codeforces Beta Round #43 (ACM-ICPC Rules), problem: (D) Parking Lot 线段树 区间合并

题意:停车位问题。当车主想选择的空位后端有车时,车主选车位是要保证和后边的车的距离不小于b,前端有车是,保证与前面车的距离不小于f。

做法:区间合并好题啊,有很多坑等我去跳。首先是要车子离开时,后边的那个序号表示的是车子到来的时刻(这里姑且表示为那辆车子是在下第i个命令的时候来的),

然后b,f的限制是车主选车的时候人为加上的,也就是说当车子停在某个位置,它与后面的车子的距离为b,然后b<f,后边那辆车的f无法满足了,这个时候也是正确的,因为b,f只是车主停车时的顾忌,停完了车,他就不管了。还有update的时候,覆盖的位置,长度,都是车尾的实际位置,车子的实际长度。

#include<cstdio>
#include<cstring>
#define eps 1e8
#define left l,m,x<<1
#define right m+1,r,x<<1|1
const int LMT=100003;
int lsum[LMT<<2],rsum[LMT<<2],msum[LMT<<2],l,b,f;
struct car
{
    int len,pos;
}ca[105];
inline int max(int a,int b)
{
    return a>b?a:b;
}
void build(int l,int r,int x)
{
    lsum[x]=rsum[x]=msum[x]=r+1-l;
    if(l==r)return;
    int m=(l+r)>>1;
    build(left);
    build(right);
}
void pushup(int x,int l,int r)
{
    int m=(l+r)>>1;
    lsum[x]=lsum[x<<1];
    rsum[x]=rsum[x<<1|1];
    if(lsum[x]==m+1-l)
        lsum[x]+=lsum[x<<1|1];
    if(rsum[x]==r-m)rsum[x]+=rsum[x<<1];
    msum[x]=max(rsum[x<<1]+lsum[x<<1|1],max(msum[x<<1],msum[x<<1|1]));
}
int query(int len,int l,int r,int x)
{
    if(l==r)return l;
    int m=(l+r)>>1;
    if(len<=msum[x<<1])return query(len,left);
    if(rsum[x<<1]+lsum[x<<1|1]>=len)return m+1-rsum[x<<1];
    return query(len,right);
}
void update(int op,int L,int R,int l,int r,int x)
{
    if(L<=l&&r<=R)
    {
        msum[x]=lsum[x]=rsum[x]=op*(r+1-l);
        return;
    }
    int m=(l+r)>>1;
    if(L<=m)update(op,L,R,left);
    if(R>m)update(op,L,R,right);
    pushup(x,l,r);
}
int main(void)
{
    int m,len,x,ord,y,cnt=0;
    scanf("%d%d%d",&l,&b,&f);
    build(0,l-1,1);
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&ord);
        if(ord==2)
        {
            scanf("%d",&x);
            x--;
            update(1,ca[x].pos,ca[x].pos+ca[x].len-1,0,l-1,1);
            cnt++;
        }
        else
        {
           scanf("%d",&len);
           if(msum[1]==l&&len<=msum[1])
           {
               puts("0");
               ca[cnt].pos=0;
               ca[cnt].len=len;
               cnt++;
               update(0,0,len-1,0,l-1,1);
                continue;
           } 
           if(lsum[1]>=len+f)
           {
               puts("0");
               ca[cnt].pos=0;
               ca[cnt].len=len;
               cnt++;
               update(0,0,len-1,0,l-1,1);
               continue;
           }
           x=y=eps;
           if(msum[1]>=len+b+f)x=query(len+b+f,0,l-1,1);
           if(rsum[1]>=len+b)y=l-rsum[1];
           if(x==y&&y==eps)
           {
               cnt++;
            puts("-1");
            continue;
           }
           if(x<y)
           {
               ca[cnt].len=len;
               ca[cnt].pos=x+b;
               cnt++;
            printf("%d\n",x+b);
            update(0,x+b,x+len+b-1,0,l-1,1);
           }
          else
          {
              ca[cnt].len=len;
              ca[cnt].pos=y+b;
              cnt++;
            printf("%d\n",y+b);
            update(0,y+b,y+len+b-1,0,l-1,1);
          }
        }
    }
    return 0;
}


 

你可能感兴趣的:(Codeforces Beta Round #43 (ACM-ICPC Rules), problem: (D) Parking Lot 线段树 区间合并)